ContentTemplateSelector

ContentTemplateSelector

本文介绍了ContentControl.ContentTemplateSelector 动态选择模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Window的右边设置了一个ContentControl,并设置了Content binding Items(它的类型是ObservableCollection).现在我想实现它:如果没有项目,ContentControl选择第一个DataTemplate,并在项目中添加一个项目,ContentControl将选择第二个DataTemplate显示一些信息.

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.

像这样:

问题是当我在items中添加一个item时,ContentControl没有更新和改变DataTemplate,我尝试设置mode、UpdateSourceTrigger等,但是失败了.在 ViewModel 中,删除项目后,我使用此语句,它会运行良好<1>:

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

但我想知道为什么它与 <1> 配合得很好.

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

已编辑 2这是声明:

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);
    }
}

推荐答案

ContentControl 将只监听 PropertyChanged 事件,而不监听 CollectionChanged 事件.您需要使用 ItemsControl 或其任何其他版本(如 ListView)来实现此行为.

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.

作为一种解决方法,您可以为 ContentControl 创建一个 Style 并定义一个 DataTrigger 而不是 TemplateSelector> 在 Items.Count 上并相应地设置 ContentTemplate.类似的东西,

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>

这篇关于ContentControl.ContentTemplateSelector 动态选择模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 22:23