我正在尝试在选择ListBoxItem时切换出ContentPresenter,同时使用多个DataTemplates来表示不同类型的数据。
以下是定义ListBox内部的UserControl:
<UserControl x:Class="Homage.View.FilePanelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vw="clr-namespace:Homage.View"
xmlns:vm="clr-namespace:Homage.ViewModel"
xmlns:ctrl="clr-namespace:Homage.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:SlugViewModel}">
<vw:SlugView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}">
<vw:HeaderSlugView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ContentSlugViewModel}">
<vw:ContentSlugView />
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="SlugContainer" Background="Transparent" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Margin="0,5,0,0" Padding="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Content="{Binding DisplayName}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="SlugContainer" Property="BorderThickness" Value="5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<ListBox ItemsSource="{Binding Slugs}" Padding="5" />
</Grid>
</UserControl>
基于要显示的数据类型(例如,“Header Slug”),将某个DataTemplate应用于ListBoxItem。这很好用,但我想将所选ListBoxItem的DataTemplate调整为另一个DataTemplate - 再次,根据显示的数据类型。
目标是,因为每种数据类型都不同,所以每种数据类型在未选中时都具有独特的外观,并且在选择时会收到一组唯一的选项。
如果我能够完成上述工作,那就太棒了!但是,我也想让事情复杂化......
虽然每种数据类型都有独特的控件,但它们也有共同的控件。因此,我希望一次定义所有常用控件,以便它们出现在ListBox中的相同位置。
<DataTemplate x:Key="CommonSelectedTemplate">
<!-- common controls -->
...
<DataTemplate x:Key="UniqueSelectedTemplate">
<!-- all the unique controls -->
<ContentPresenter />
</DataTemplate>
<!-- more common controls -->
...
</DataTemplate>
如果我必须多次定义所有常见的东西(现在),我会活下去。 =)
感谢您的帮助!
答案 0 :(得分:0)
我们假设我们只有两种数据类型:Item1ViewModel
和Item2ViewModel
。因此,我们需要4个数据模板:2个用于公共状态,2个用于选定状态。
<DataTemplate x:Key="Template1" DataType="local:Item1ViewModel">
<TextBlock Text="{Binding Property1}" Foreground="Red" />
</DataTemplate>
<DataTemplate x:Key="Template2" DataType="local:Item2ViewModel">
<TextBlock Text="{Binding Property2}" Foreground="Blue" />
</DataTemplate>
<DataTemplate x:Key="Template1Selected" DataType="local:Item1ViewModel">
<TextBlock Text="{Binding Property1}" Background="Yellow" Foreground="Red" />
</DataTemplate>
<DataTemplate x:Key="Template2Selected" DataType="local:Item2ViewModel">
<TextBlock Text="{Binding Property2}" Background="Yellow" Foreground="Blue" />
</DataTemplate>
要根据不同的类型在两个模板之间切换内容,我使用DataTemplateSelector
类:
public class SampleTemplateSelector:DataTemplateSelector
{
public DataTemplate Type1Template { get; set; }
public DataTemplate Type2Template { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is Item1ViewModel)
return Type1Template;
else if (item is Item2ViewModel)
return Type2Template;
return null;
}
}
我们需要这个选择器的两个实例:一个用于公共状态,一个用于选择状态。
<local:SampleTemplateSelector x:Key="templateSelector"
Type1Template="{StaticResource Template1}"
Type2Template="{StaticResource Template2}"/>
<local:SampleTemplateSelector x:Key="selectedTemplateSelector"
Type1Template="{StaticResource Template1Selected}"
Type2Template="{StaticResource Template2Selected}"/>
之后你应该添加这个代码来切换两个选择器:
<DataTemplate x:Key="ListItemTemplate">
<ContentControl x:Name="content" Content="{Binding}" ContentTemplateSelector="{StaticResource templateSelector}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<Setter TargetName="content" Property="ContentTemplateSelector" Value="{StaticResource selectedTemplateSelector}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
就是这样,将此ItemTemplate
应用到ListBox
而不更改ControlTemplate
:
<ListBox ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ListItemTemplate}" />