Заполнение шаблона сообщения

270
18 ноября 2017, 09:23

Пишу чат. Отрисовал шаблон сообщения в usercontrol.

<UserControl x:Class="ChatMessage.MessageView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:ChatMessage"
         mc:Ignorable="d" 
         d:DesignHeight="44" d:DesignWidth="250">
<Grid>
    <StackPanel Margin="0 4 0 0" Width="36" Height="36" VerticalAlignment="Top"  HorizontalAlignment="Left" Orientation="Horizontal">
        <Image Source="Resources/admin.png"/>            
    </StackPanel>
    <StackPanel Margin="36 0 0 0" Height="22" HorizontalAlignment="Left" Orientation="Horizontal" VerticalAlignment="Top">
        <TextBlock Margin="6 0 0 4" FontSize="15" FontFamily="Lato" FontWeight="Bold">Username</TextBlock>
        <TextBlock Margin="4 4 0 4" FontSize="11" FontFamily="Lato" FontWeight="Light">8:23 AM</TextBlock>
    </StackPanel>
    <StackPanel Margin="42 22 0 0" Orientation="Horizontal">
        <TextBlock FontFamily="Loto" FontSize="13" FontWeight="Regular" Text="Hey!What's going on?"/>
    </StackPanel>      
</Grid>

научился вызывать его в codebehind mainwindow и добавлять в listview

        MessageView mv = new MessageView();           
        ListMessage.Items.Add(mv);

полагаю теперь самая сложная задача, как написать код, чтобы при вызове usercontrol, в codebehind mainwindow, к нему добавлялся image, username, date и message в соответствующие поля шаблона usercontrol.

Answer 1

Смотрите. Для того, чтобы параметризировать ваш UserControl, вам нужно добавить в него свойства. Точнее, dependency property. Знаете, как это делается? (Если нет, почитайте про сниппеты, вам нужен propdp.)

Итак, не мудрствуя лукаво, нам понадобятся свойства string UserName, DateTime Date и string Text. Когда вы добавите их в ваш UserControl, у вас получится что-то вроде такого:

public string UserName
{
    get { return (string)GetValue(UserNameProperty); }
    set { SetValue(UserNameProperty, value); }
}
public static readonly DependencyProperty UserNameProperty =
    DependencyProperty.Register("UserName", typeof(string), typeof(MessageView));

Теперь, значения свойств нужно отобразить. Для этого немного поменяем XAML-разметку:

<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
                                AncestorType=UserControl}}"
      TextBlock.FontFamily="Loto">
    <!-- начальный кусок пропустил -->
    <StackPanel Margin="36 0 0 0" Height="22"
                HorizontalAlignment="Left" Orientation="Horizontal" VerticalAlignment="Top">
        <TextBlock Margin="6 0 0 4" FontSize="15" FontWeight="Bold"
                   Text="{Binding UserName}" />
        <TextBlock Margin="4 4 0 4" FontSize="11" FontWeight="Light"
                   Text="{Binding Date, StringFormat=t}"/>
    </StackPanel>
    <StackPanel Margin="42 22 0 0" Orientation="Horizontal">
        <TextBlock FontSize="13" FontWeight="Regular"
                   Text="{Binding Text}"/>
    </StackPanel>      
</Grid>

Объяснение:

  1. Я установил DataContext на сам UserControl, чтобы привязываться к свойствам было проще. (Привязка ведётся по умолчанию к DataContext'у.)
    • DataContext установлен внутри, не у самого UserControl'а, т. к. пользователь обычно хочет дать свой DataContext всему контролу, чтобы привязывать его свойства.
  2. Я вынес общее свойство текста FontFamily наружу, чтобы не устанавливать его каждый раз
  3. Значения UserName, Date и Text привязываются к свойствам через Binding. Вручную их больше устанавливать не нужно.
    • Значение Date привязывается с указанием формата строки. t означает короткий формат, содержащий только время.

Теперь, как этим пользоваться? Очень просто. Если вы не используете MVVM, а создаёте контролы в code-behind, то

MessageView mv = new MessageView()
{
    UserName = "Василий",
    Date = new DateTime(2017, 11, 16, 8, 23, 00),
    Text = "Hey! What's going on?"
};

Если вы пользуетесь MVVM, у вас будет что-то наподобие

<ListView ItemsSource="{Binding AllMessages}">
   <ListView.ItemTemplate>
       <DataTemplate>
           <local:MessageView
               UserName="{Binding UserName}" Text="{Binding Text}" Date="{Binding Date}"/>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>
Answer 2

@VladD: В общем потестил, главное в listview отключить горизонтальный скрол, а все остальное ни как не влияет. Если установить максимальную длину строки у textblock 'a, то текст нужно еще выравнивать по левому краю иначе все оставшееся место из maxwidth, которое не занял текст он использует как пропорциональный margin по левому и правому краю, то есть как бы произойдет центрирование текста. Конечный вариант выглядит следующим образом:

<TextBlock Margin="42 22 0 0"
               FontSize="13" FontWeight="Regular"
               TextWrapping="Wrap" Text="{Binding Text}"/>
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
          Name="ListMessage" Grid.Row="0"/>
READ ALSO
Как перезапустить Awesomium?

Как перезапустить Awesomium?

Использую awesomium вместо стандартного компонента браузераНужно изменить user agent

258
Есть ли возможность извлечь данные из файла .dwg, используя C#(желательно в excel)?

Есть ли возможность извлечь данные из файла .dwg, используя C#(желательно в excel)?

Нужно достать параметры некоторого объекта изdwg файла

253
&ldquo;Имя типа&rdquo; не существует в текущем контексте

“Имя типа” не существует в текущем контексте

Создал новый проект, сделал форму, добавил кнопку(search)Хочу при нажатии на кнопку открывать форму(searchUsers) из другой сборки

453