Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 子元素更改时更改ListView.ItemTemplate_Wpf_Xaml_Listview_Itemtemplate - Fatal编程技术网

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