Меня интересует как можно сделать отображение сообщений как в outlook,т.е есть список и отображается какая-то информация,например отправитель,тема,когда было отправлено, и только по нажатию на само сообщение видно оно целиком.
Если важно:сообщения я получаю при помощи ImapClient(нужно именно его использовать по заданию).Пример того,чего я хочу добиться в итоге, на картинке.

- 28,687
- 464
1 Answers
Покажу простейший пример подобного функционала...
Данные
Для начала создадим модель нашего сообщения, пусть там будет информация об авторе, дата, ну и сам текст:
public class MessageModel { public MessageModel(string autor, DateTime date, string text) { Autor = autor; DateTime = date; Text = text; } public string Autor { get; set; } public DateTime DateTime { get; set; } public string Text { get; set; } }Далее создадим коллекцию, которая будет содержать наши сообщения, пусть это будет в
MainWindow, прям в самом начале класса пишем:public ObservableCollection<MessageModel> Messages { get; set; } = new ObservableCollection<MessageModel>();В конструкторе
MainWindow()заполним нашу коллекцию и зададимDataContext:public MainWindow() { InitializeComponent( ); Messages.Add(new MessageModel("User 1", DateTime.Now, "Привет мир!")); Messages.Add(new MessageModel("User 2", DateTime.Now, "Хочу кушать....")); DataContext = this; }Все, простейшие данные для привязки у нас есть, осталось реализовать интерфейс.
Интерфейс
Создадим
Grid, который будет разделять наше пространство на 2 колонки:<Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> </Grid>В левой части пусть будет отображение всех сообщений и возьмем только автора и дату. Для этого нам надо задать шаблон
ItemTemplate. Также, мы уже сейчас можем указать привязку,ItemsSource:<ListBox Grid.Column="0" ItemsSource="{Binding Messages}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Autor}"/> <TextBlock Text="{Binding DateTime}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>В левую часть, давайте поместим сверху автора, дату, а снизу пусть все пространство будет занято сообщением. Ну а также, давайте привяжем все элементы к выбранному элементу нашего списка, делается это очень просто! Все элементы мы привязываем как обычно, но только с указанием еще имени нашей коллекции, то есть вот так:
{Binding Messages/Autor}, а также у нашегоListBoxнадо указатьIsSynchronizedWithCurrentItem="True". Таким образом при клике на объект вListBoxмы будем видеть нужные данные в левой части:<Grid Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Margin="5,0"> <TextBlock Text="{Binding Messages/Autor}"/> <TextBlock Text="{Binding Messages/DateTime}" Margin="5,0,0,0"/> </StackPanel> <TextBlock Grid.Row="1" Text="{Binding Messages/Text}"/> </Grid>
Вся разметка целиком у нас получится такая:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" ItemsSource="{Binding Messages}" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Autor}"/>
<TextBlock Text="{Binding DateTime}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="5,0">
<TextBlock Text="{Binding Messages/Autor}"/>
<TextBlock Text="{Binding Messages/DateTime}" Margin="5,0,0,0"/>
</StackPanel>
<TextBlock Grid.Row="1" Text="{Binding Messages/Text}"/>
</Grid>
</Grid>
Проверка
p.s. тут много чего нету, вам как минимум еще нужно будет реализовывать INotifyPropertyChanged да и много чего еще. Но на первое время, думаю вполне подходящий вариант. Удачи!
Менять элементы в listbox при смене combobox
Тут все по сути тоже самое:
В наш класс MessageModel добавим для теста коллекцию, пусть это будет обычный
string[]с названием TestCollection. Тогда наш класс превратится в что то на подобии этого:public class MessageModel { public MessageModel(string autor, DateTime date, string text, string[] testCollection) { Autor = autor; DateTime = date; Text = text; TestCollection = testCollection; } public string Autor { get; set; } public DateTime DateTime { get; set; } public string Text { get; set; } public string[] TestCollection { get; set; } }Далее допишем заполнение данных:
Messages.Add(new MessageModel("User 1", DateTime.Now, "Привет мир!", new[] {"aaa", "bbb"})); Messages.Add(new MessageModel("User 2", DateTime.Now, "Хочу кушать....", new[] { "111", "222" }));Дальше для примера перепишем немного разметку (заменим левый ListBox на ComboBox, а в правую часть заместо текста выведем наш
string[]):
ComboBox я перепишу по топорному из уже имеющегося ListBox:
<ComboBox Grid.Column="0" ItemsSource="{Binding Messages}" IsSynchronizedWithCurrentItem="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Autor}"/>
<TextBlock Text="{Binding DateTime}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Ну а справа TextBox давайте заменим (для примера) на ListBox, который будет привязан к нашему string[]:
<ListBox Grid.Row="1" ItemsSource="{Binding Messages/TestCollection}"/>
- Вот собственно и все, мы вывели привязали ComboBox и его внутреннюю коллекцию привязали к другому ListBox. Проверим:
- 15,694


p.s. тут много чего нету, вам как минимум еще нужно будет реализовывать INotifyPropertyChanged... да и много чего еще1. Вопрос: не могли бы вы перечислить перечень, что ещё требуется? Просто ключевые слова... – eusataf Apr 30 '23 at 05:31DataContextи данные в конструкторе окна, когда как данные должны быть в отдельном классе (может вообще в базе, а значит нужен для нее отдельно Model/ViewModel слои), аDataContextдолжен быть задан за пределами окна. INPC тут также нету, данные не будут обновлены при редактировании через код. Остальное все по желанию. – EvgeniyZ Apr 30 '23 at 10:41