Listbox with custom datatemplate

2019-08-04 12:42发布

问题:

Hi I do windows store app like icq but mine is very simple. But now I have problem because I dont know how make template with binding which will look like this:

my listbox look is here:

https://www.dropbox.com/s/we5m3h5ch6mop1j/messageListbox.PNG https://www.dropbox.com/s/6uypyjb4etxc4sk/myMessageListbox.PNG.

Can anyone advise me how I can make a listbox that will contain two kinds messages - say the message from me and from someone else(left and right). In short same teplate like icq. Thx for willingness.

  <ListBox x:Name="lbChoosenMessagesUsers"  Grid.Column="3" FontSize="13" ItemsSource="{Binding MyDatasCurentUser}" Margin="0,0,50,0">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="IsEnabled" Value="False"/>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Polygon Margin="10,10,0,0" Points="0,0 20,10, 0,10" Fill="#BFE8FF" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" VerticalAlignment="Top">
                            <Polygon.RenderTransform>
                                <CompositeTransform Rotation="-181"/>
                            </Polygon.RenderTransform>
                        </Polygon>
                        <Grid  Margin="27,0,0,0"  HorizontalAlignment="Left" Background="#BFE8FF" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"></RowDefinition>
                                <RowDefinition Height="auto"></RowDefinition>
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding MessengerText}" HorizontalAlignment="Left"  Margin="5,5,20,0" VerticalAlignment="Top" Foreground="black"></TextBlock>
                            <TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding MessengerTime}" HorizontalAlignment="Left"  Margin="5,0,0,5" VerticalAlignment="Bottom" FontSize="9" Foreground="#908C8C"></TextBlock>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

回答1:

The simplest way are Triggers. But much flexible are DataTemplates.

Let say your MyDatasCurentUser collection is type of Message. And I'm sure that Message contains some flag saying that if it is incoming/outgoing message:

 public bool IsIncoming { get; set; }

Now you need to create DataTemplateSelector class:

namespace StackOverFlow
{
          public class TemplateSelector : DataTemplateSelector
          {
            public DataTemplate IncomingMessageTemplate { get; set; }
            public DataTemplate OutgoingMessageCaptureTemplate { get; set; }
            public DataTemplate EmptyTemplate { get; set; }

            public override DataTemplate SelectTemplate(object item, DependencyObject container)
            {
              var x = item as Message;
              if (x != null)
              {
                return (x.IsIncoming) ? IncomingMessageTemplate : OutgoingMessageCaptureTemplate;
              }

              return EmptyTemplate;
            }
          }
}

And in XAML you need reference TemplateSelector and create datatemplates:

<UserControl x:Class="StackOverFlow.UserControl1"
             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:stackOverFlow="clr-namespace:StackOverFlow"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
         <!-- Template for INCOMNIG messages -->
          <DataTemplate x:Key="IncomnigTemplate">
            <Grid>
              <Polygon Margin="10,10,0,0" Points="0,0 20,10, 0,10" Fill="#BFE8FF" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Polygon.RenderTransform>
                 <CompositeTransform Rotation="-181"/>
                </Polygon.RenderTransform>
              </Polygon>
              <Grid  Margin="27,0,0,0"  HorizontalAlignment="Left" Background="#BFE8FF" >
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                  <RowDefinition Height="auto"></RowDefinition>
                  <RowDefinition Height="auto"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding MessengerText}" HorizontalAlignment="Left"  Margin="5,5,20,0" VerticalAlignment="Top" Foreground="black"></TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding MessengerTime}" HorizontalAlignment="Left"  Margin="5,0,0,5" VerticalAlignment="Bottom" FontSize="9" Foreground="#908C8C"></TextBlock>
              </Grid>
            </Grid>
          </DataTemplate>

         <!-- Template for OUTGOING messages -->            
          <DataTemplate x:Key="OutgoinTemplate">
            <Grid>
              <Polygon Margin="10,10,0,0" Points="0,0 20,10, 0,10" Fill="Gray" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Right" VerticalAlignment="Top">
                <Polygon.RenderTransform>
                  <CompositeTransform Rotation="0"/>
                </Polygon.RenderTransform>
              </Polygon>
              <Grid  Margin="27,0,0,0"  HorizontalAlignment="Right" Background="Gray" >
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                  <RowDefinition Height="auto"></RowDefinition>
                  <RowDefinition Height="auto"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding MessengerText}" HorizontalAlignment="Left"  Margin="5,5,20,0" VerticalAlignment="Top" Foreground="black"></TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding MessengerTime}" HorizontalAlignment="Left"  Margin="5,0,0,5" VerticalAlignment="Bottom" FontSize="9" Foreground="#908C8C"></TextBlock>
              </Grid>
            </Grid>
          </DataTemplate>

         <!-- Our cool datatemplate selector -->
          <stackOverFlow:TemplateSelector x:Key="MessageTemplateSelector"
                                          EmptyTemplate="{x:Null}"
                                          IncomingMessageTemplate="{StaticResource IncomnigTemplate}"
                                          OutgoingMessageCaptureTemplate="{StaticResource OutgoinTemplate}"
            />
    </UserControl.Resources>
      <!-- Don't forget ItemTemplateSelector attribute -->
      <ListBox ItemTemplateSelector="{StaticResource MessageTemplateSelector}" x:Name="lbChoosenMessagesUsers"  Grid.Column="3" FontSize="13" ItemsSource="{Binding MyDatasCurentUser}" Margin="0,0,50,0">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="IsEnabled" Value="False"/>
                    </Style>
                </ListBox.ItemContainerStyle>
            </ListBox>
    </UserControl>