Change ListView.ItemTemplate on subelement change

自闭症网瘾萝莉.ら 提交于 2019-12-11 08:03:23

问题


let's say we have simple data class:

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

and an ObservableCollection of objects of this class. I want to have this collection displayed in a ListView with seperated DataTemplated which is distinguished by Ex.Prop2 (if it is null or empty then template01 is used, otherwise template02). This property can be changed in runtime so simple "trick" with ListView.ItemTemplateSelector does not work :(

How to achieve this functionality? Is it possible to achieve it any other way than listening to NotifyPropertyChanged on each object of the collection and than changing manually the template?

Thanks for your help.

Below piece of code which I already have:

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

回答1:


Instead of using a TemplateSelector, you can have a single DataTemplate containing two Grids, which switch visibility dependent on the property values.

Here is an example:

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

Obviously you could replace the TextBlock elements with UserControls representing your two DataTemplates.

If you want, you can also remove the need for the bulky Styles by binding Grid.Visibility to a property (named, for example, IsVisible) on your ViewModel and using a VisibilityConverter.




回答2:


I usually just use a ContentControl which changes its ContentTemplate based on a DataTrigger. DataTriggers respond to the value getting changed, while DataTemplateSelectors do not

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

You could also use a Converter that returns String.IsNullOrEmpty(value) if you wanted a single DataTrigger



来源:https://stackoverflow.com/questions/8935052/change-listview-itemtemplate-on-subelement-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!