c# - ContentControl.ContentTemplateSelector 动态选择模板

标签 c# wpf mvvm contenttemplateselector

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

像这样:

enter image description here

问题是当我将一个项目添加到项目中时,ContentControl 没有更新和更改 DataTemplate,我尝试设置模式、UpdateSourceTrigger 等,但都失败了。在 ViewModel 中,删除一个项目后,我使用这个语句,它会很好地工作<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;
    }
}

已编辑: 删除一项后使用这种方式也失败:

RaisePropertyChanging(ItemsPropertyName);
RaisePropertyChanged(ItemsPropertyName);

但我想知道为什么它与 <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 创建一个 Style,而不是 TemplateSelector,定义一个 DataTriggerItems.Count 上并相应地设置 ContentTemplate。 类似的东西,

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

关于c# - ContentControl.ContentTemplateSelector 动态选择模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20468126/

相关文章:

c# - .NET Windows 窗体设计时规则

c# - 上传到托管服务器后 Entity Framework 连接错误

c# - 如何在 WPF 中创建一个只接受数字和一个只接受字母的文本框?

C#:使用数据绑定(bind)文本框在 List<Customer> 中导航

c# - 关于使用 Caliburn.Micro MVVM WPF 进行 View 导航的建议

c# - 什么时候可以将 2 个 View 模型合并为 1 个而不是使用某种形式的 View 模型- View 模型通信?

c# - 在 Startup 中将 ApplicationDbContext 注入(inject)到 Configure 方法中

c# - 在Windows Phone运行时应用程序中使用Xna Framework类

使用 GroupStyle 时 WPF 多页 Listview 打印

javascript - knockout 3.x : markup inside element referencing a named template is wiped out