Изменить ListView.ItemTemplate при изменении подэлемента - PullRequest
1 голос
/ 20 января 2012

скажем, у нас есть простой класс данных:

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

и ObservableCollection объектов этого класса. Я хочу, чтобы эта коллекция отображалась в ListView с разделенным DataTemplated, который отличается от Ex.Prop2 (если он нулевой или пустой, то используется 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 ]

3 голосов
/ 20 января 2012

Вместо использования 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>

Очевидно, выможет заменить элементы TextBlock элементами UserControls, представляющими ваши два DataTemplates.

Если вы хотите, вы также можете устранить необходимость в громоздких стилях, привязав Grid.Visibility к свойству (названному, например, IsVisible) вViewModel и использование VisibilityConverter.

1 голос
/ 20 января 2012

Я обычно просто использую 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), если вы хотите один DataTrigger

...