ItemsControl基于内容的不同模板

本文关键字:于内容 ItemsControl | 更新日期: 2023-09-27 18:29:11

请确定以下不起作用的原因,我正在尝试实现一个聊天消息窗口,在该窗口中,每条消息都将根据MessageDirection呈现不同的风格。为此,我使用了一个绑定到Messages属性的ItemsControl

在ChatWindow类中,我有以下

public static readonly DependencyProperty MessagesProperty = DependencyProperty.Register(
        "Messages",
        typeof(ObservableCollection<Message>),
        typeof(ChatWindow),
        new PropertyMetadata(null));
public ObservableCollection<Message> Messages
{
    get
    {
        return (ObservableCollection<Message>)this.GetValue(MessagesProperty);
    }
    set
    {
        this.SetValue(MessagesProperty, value);
    }
}

我在ResourceDictionary 中定义了以下内容

<ScrollViewer x:Name="srcMessages" Margin="0,0,0,0" VerticalScrollBarVisibility="Visible">
    <StackPanel>
        <ItemsControl ItemsSource="{Binding Path=Messages, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatWindow}}}" x:Name="Messages">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <chat:MessageContentPresenter Content="{Binding}">
                        <chat:MessageContentPresenter.InboundTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="94" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="*" />
                                        </Grid.ColumnDefinitions>
                                        <StackPanel Grid.Column="1" Orientation="Horizontal">
                                            <TextBlock Text="Username One" FontSize="10" Foreground="#adadad"></TextBlock>
                                            <TextBlock Text=" - " FontSize="10" Foreground="#adadad"></TextBlock>
                                            <TextBlock Text="11:45 AM" FontSize="10" Foreground="#adadad"></TextBlock>
                                        </StackPanel>
                                    </Grid>
                                    <Grid Grid.Row="1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="18" />
                                            <ColumnDefinition Width="65" />
                                            <ColumnDefinition Width="5" />
                                            <ColumnDefinition Width="6" />
                                            <ColumnDefinition Width="230" />
                                            <ColumnDefinition Width="*" />
                                        </Grid.ColumnDefinitions>
                                        <Image Grid.Column="1" Height="60" Width="60" Source="pack://siteoforigin:,,,/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                            <Image.Clip>
                                                <EllipseGeometry Center="30,30" RadiusX="30" RadiusY="30" />
                                            </Image.Clip>
                                        </Image>
                                        <Polygon Grid.Column="3" Points="0,0 -4,3 0,6 0,0" StrokeThickness="2" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="#d8d7dc" Stroke="#d8d7dc"></Polygon>
                                        <Border Grid.Column="4" BorderBrush="#d8d7dc" BorderThickness="1" Background="#d8d7dc" Padding="5">
                                            <TextBlock TextWrapping="Wrap" Text="This is a message in a chat window..." VerticalAlignment="Top" FontSize="12" Foreground="#000000"></TextBlock>
                                        </Border>
                                    </Grid>
                                </Grid>
                            </DataTemplate>
                        </chat:MessageContentPresenter.InboundTemplate>
                        <chat:MessageContentPresenter.OutboundTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="94" />
                                        </Grid.ColumnDefinitions>
                                        <StackPanel Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
                                            <TextBlock Text="Username One" FontSize="10" Foreground="#adadad"></TextBlock>
                                            <TextBlock Text=" - " FontSize="10" Foreground="#adadad"></TextBlock>
                                            <TextBlock Text="11:45 AM" FontSize="10" Foreground="#adadad"></TextBlock>
                                        </StackPanel>
                                    </Grid>
                                    <Grid Grid.Row="1">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="230" />
                                            <ColumnDefinition Width="6" />
                                            <ColumnDefinition Width="5" />
                                            <ColumnDefinition Width="65" />
                                            <ColumnDefinition Width="18" />
                                        </Grid.ColumnDefinitions>
                                        <Image Grid.Column="4" Height="60" Width="60" Source="pack://siteoforigin:,,,/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                            <Image.Clip>
                                                <EllipseGeometry Center="30,30" RadiusX="30" RadiusY="30" />
                                            </Image.Clip>
                                        </Image>
                                        <Polygon Grid.Column="2" Points="0,0 4,3 0,6 0,0" StrokeThickness="2" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="#4fcd00" Stroke="#4fcd00"></Polygon>
                                        <Border Grid.Column="1" BorderBrush="#4fcd00" BorderThickness="1" Background="#4fcd00" Padding="5">
                                            <TextBlock TextWrapping="Wrap" Text="This is a message in a chat window..." VerticalAlignment="Top" FontSize="12" Foreground="#000000"></TextBlock>
                                        </Border>
                                    </Grid>
                                </Grid>
                            </DataTemplate>
                        </chat:MessageContentPresenter.OutboundTemplate>
                    </chat:MessageContentPresenter>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

MessageContentPresenter如下

public class MessageContentPresenter : ContentControl
{
    #region Public Properties
    public DataTemplate InboundTemplate { get; set; }
    public DataTemplate OutboundTemplate { get; set; }
    #endregion
    #region Methods
    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);
        var message = newContent as Message;
        if (message.Direction == MessageDirection.Inbound)
        {
            this.ContentTemplate = this.InboundTemplate;
        }
        else
        {
            this.ContentTemplate = this.OutboundTemplate;
        }
    }
    #endregion
}

当我运行这段代码时,一切都很好,OnContentChanged方法对Messages集合中的每个项执行一次。问题是InboundTemplateOutboundTemplate都是null

我真的不明白问题出在哪里,也不明白为什么这两个模板都是null,非常感谢您的帮助。

ItemsControl基于内容的不同模板

实际上,您可以使用DataTemplateSelector。

但另一种选择是使用DataTemplate+ContentControl和Style:

首先,由于我们不需要MessageContentPresenter类,请删除它。因此,您需要从XAML中删除ItemsControl.ItemTemplate

其次,将DataTemplate+ContentControl和Style添加到Window.Resources.

试试这个给你一些线索:

<DataTemplate DataType="{x:Type local:Message}">
        <ContentControl Content="{Binding Direction}">
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Direction}" Value="{x:Static local:MessageDirection.Inbound}">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <Button Background="Green">Inbound</Button>
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Direction}" Value="{x:Static local:MessageDirection.Outbound}">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <Button Background="Red">Outbound</Button>
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>