Wpf 子元素更改时更改ListView.ItemTemplate
假设我们有一个简单的数据类:Wpf 子元素更改时更改ListView.ItemTemplate,wpf,xaml,listview,itemtemplate,Wpf,Xaml,Listview,Itemtemplate,假设我们有一个简单的数据类: public class Ex { public string Prop1 {...} // notify property public string Prop2 {...} // notify property } 以及这类对象的可观察集合。我希望将此集合显示在一个列表视图中,并使用单独的DataTemplated来区分Ex.Prop2(如果为null或空,则使用template01,否则使用template02)。此属性可以在运行时更改,因此
public class Ex {
public string Prop1 {...} // notify property
public string Prop2 {...} // notify property
}
以及这类对象的可观察集合。我希望将此集合显示在一个列表视图中,并使用单独的DataTemplated来区分Ex.Prop2(如果为null或空,则使用template01,否则使用template02)。此属性可以在运行时更改,因此ListView.ItemTemplateSelector的简单“技巧”不起作用:(
如何实现此功能?除了侦听集合中每个对象上的NotifyPropertyChanged和手动更改模板之外,是否还有其他方法可以实现此功能
谢谢你的帮助
下面是我已经拥有的一段代码:
<ListView x:Name="lstTerms"
ItemsSource="{Binding Game.Words}"
HorizontalContentAlignment="Stretch"
Grid.IsSharedSizeScope="True">
<ListView.ItemContainerStyle>
<Style>
<Setter Property="Control.Padding" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<!-- checks if element is null or its Prop2 is null or empty. If so, uses NullTemplate -->
<ListView.ItemTemplateSelector>
<local:MySelectTemplate
NormalTemplate="{StaticResource NormalItemTemplate}"
NullTemplate="{StaticResource NullItemTemplate}" />
</ListView.ItemTemplateSelector>
</ListView>
不使用TemplateSelector,您可以使用一个包含两个网格的DataTemplate,这两个网格根据属性值切换可见性 以下是一个例子:
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Background="LightBlue" Name="normalGrid">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Prop1}" Value="{x:Null}">
<Setter Property="Grid.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding Prop1}"></TextBlock>
</Grid>
<Grid Background="Green" Name="nullGrid">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=normalGrid, Path=Visibility}" Value="Visible">
<Setter Property="Grid.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding Prop2}"></TextBlock>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
显然,您可以用表示两个数据模板的UserControls替换TextBlock元素
如果需要,还可以通过将Grid.Visibility绑定到属性(例如,命名为IsVisible)来消除对庞大样式的需求在ViewModel上,使用VisibilityConverter。您可以使用一个包含两个网格的DataTemplate来代替TemplateSelector,这两个网格根据属性值切换可见性 以下是一个例子:
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Background="LightBlue" Name="normalGrid">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Prop1}" Value="{x:Null}">
<Setter Property="Grid.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding Prop1}"></TextBlock>
</Grid>
<Grid Background="Green" Name="nullGrid">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=normalGrid, Path=Visibility}" Value="Visible">
<Setter Property="Grid.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding Prop2}"></TextBlock>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
显然,您可以用表示两个数据模板的UserControls替换TextBlock元素
如果需要,还可以通过将Grid.Visibility绑定到属性(例如,命名为IsVisible)来消除对庞大样式的需求在ViewModel上,使用VisibilityConverter。我通常只使用
ContentControl
,它根据DataTrigger
更改其ContentTemplate
。DataTriggers响应更改的值,而DataTemplateSelector
则不响应
<Style x:Key="SomeStyleKey" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Prop2}" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{StaticResource NullTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Prop2}" Value="">
<Setter Property="ContentTemplate" Value="{StaticResource NullTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
...
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl Style="{StaticResource SomeStyleKey}" />
</DataTemplate>
</ListView.ItemTemplate>
...
还可以使用返回
String.IsNullOrEmpty(值)的转换器
如果需要单个数据触发器
我通常只使用内容控件
,该控件基于数据触发器
更改其内容模板
。数据触发器响应更改的值,而数据模板选择器
不响应
<Style x:Key="SomeStyleKey" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Prop2}" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{StaticResource NullTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Prop2}" Value="">
<Setter Property="ContentTemplate" Value="{StaticResource NullTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
...
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl Style="{StaticResource SomeStyleKey}" />
</DataTemplate>
</ListView.ItemTemplate>
...
还可以使用返回String.IsNullOrEmpty(值)的转换器
如果你想要一个单一的数据触发器
我实际上使用了这种方法,但Rachel的方法也很好。我不知道为什么我不自己想到这些……太多的工作会杀死你;我实际上使用了这种方法,但Rachel的方法也很好。我不知道为什么我不自己想到这些……太多的工作会杀死你;D