更改子元素更改时的ListView.ItemTemplate

时间:2012-01-19 23:46:57

标签: wpf xaml listview itemtemplate

假设我们有简单的数据类:

public class Ex {
    public string Prop1 {...} // notify property
    public string Prop2 {...} // notify property
}

和此类对象的ObservableCollection。我想让这个集合显示在一个ListView中,并带有分隔的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>

2 个答案:

答案 0 :(得分:3)

您可以拥有一个包含两个Grids的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>

显然,您可以使用代表两个DataTemplates的UserControl替换TextBlock元素。

如果需要,还可以通过将Grid.Visibility绑定到ViewModel上的属性(例如,IsVisible)并使用VisibilityConverter来删除对庞大样式的需要。

答案 1 :(得分:1)

我通常只使用ContentControl根据ContentTemplate更改其DataTrigger。 DataTriggers响应变化的值,而DataTemplateSelectors

<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>

如果您想要一个Converter

,您还可以使用返回String.IsNullOrEmpty(value)的{​​{1}}