ContentControl.ContentTemplateSelector dynamically select template

倖福魔咒の 提交于 2019-12-22 04:48:18

问题


I set a ContentControl in the right of Window, and set Content binding Items (it's type is ObservableCollection). Now I want to achieve it: if there are no item, ContentControl select first DataTemplate, and add a item into items, ContentControl will select second DataTemplate to display some info.

Like this:

The problem is when I add one item into items, ContentControl didnot update and change DataTemplate, I have a try to set mode, UpdateSourceTrigger, etc., but failed. In ViewModel, after delete a item, I use this statements, it will work well <1>:

private void ExecuteDeleteClientCommand()
{
    ...
    if (DeleteClient(item))
    {
        ObservableCollection<MyViewModel> tmp = TabItems;
        TabItems = null;
        TabItems = tmp;
    }
}

.

<ContentControl 
    ContentTemplateSelector="{StaticResource MyDataTemplateSelector}" 
    Content="{Binding Items}"/>

.

public class SingleClientDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, 
        DependencyObject container)
    {
        ObservableCollection<MyViewModel> obj = 
            item as ObservableCollection<MyViewModel>;
        if (null == obj || 0 == obj.Count)
        {
            return App.Current.FindResource("NullItemDataTemplate") as DataTemplate;
        }
        return App.Current.FindResource("DefaultDataTemplate") as DataTemplate;
    }
}

Edited: use this way is also failed after delete one item:

RaisePropertyChanging(ItemsPropertyName);
RaisePropertyChanged(ItemsPropertyName);

but I wonder why it work well with <1>.

Edited2 It's the delcaration:

public const string ItemsPropertyName = "Items";
private ObservableCollection<MyViewModel> items = new ObservableCollection<MyViewModel>();
public ObservableCollection<SingleClientDetailViewModel> TabItems
{
    get { return items; }
    set 
    { 
        if (items == value) { return;}
        RaisePropertyChanging(ItemsPropertyName);
    items = value;
    RaisePropertyChanged(ItemsPropertyName);
    }
}

回答1:


ContentControl will listen only for PropertyChanged events and not for CollectionChanged event. You'll need to use either an ItemsControl or any of its other versions like ListView for this behavior.

As a workaround, you can create a Style for the ContentControl and instead of TemplateSelector, define a DataTrigger on Items.Count and set the ContentTemplate accordingly. Something like,

        <ContentControl Content="{Binding Items}">
        <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Setter Property="ContentTemplate" Value="{StaticResource DefaultDataTemplate}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Items}" Value="{x:Null}">
                        <Setter Property="ContentTemplate" Value="{StaticResource NullItemDataTemplate}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=Items.Count}" Value="0">
                        <Setter Property="ContentTemplate" Value="{StaticResource NullItemDataTemplate}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>


来源:https://stackoverflow.com/questions/20468126/contentcontrol-contenttemplateselector-dynamically-select-template

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