绑定到List<>的WPF上下文菜单依赖属性

时间:2010-03-17 15:26:21

标签: c# wpf data-binding xaml contextmenu

我试图让一个依赖属性列表的内容显示在WPF上下文菜单中。

我有一个具有以下依赖项属性的类,一个Foo列表(数据保持类):

    public List<Foo> FooList
    {
        get { return (List<Foo>)GetValue(FooListProperty); }
        set { SetValue(FooListProperty, value); }
    }
    public static DependencyProperty FooListProperty =
        DependencyProperty.Register("FooList", typeof(List<Foo>),
            typeof(FooButton));

在XAML中我设置了以下静态资源,我认为它是必需的,因为上下文菜单不是可视化树的一部分:

<UserControl.Resources>
    <ResourceDictionary>            
        <CollectionViewSource 
            x:Key="FooListSource"
            Source="{Binding FooList}"/>

        <!-- ... -->

    </ResourceDictionary>
</UserControl.Resources>

上面的ResourceDictionary的一部分是一个CompositeCollection,它需要使项目显示在实际的上下文菜单中。如果UserControl CanStop属性为true,我们还会显示分隔符和停止命令。虽然MenuItems本身出现,但这些绑定也会失败。所以,如果我能弄清楚这些失败的原因,List可能会更容易。

<CompositeCollection x:Key="FooListItems">
    <CollectionContainer 
        Collection="{Binding Source={StaticResource FooListSource}}"/>
    <Separator 
        Visibility="{Binding CanStop,
            Converter={StaticResource VisibleIfTrue}}" />
    <MenuItem 
        Command="{x:Static Buttons:FooButton.Stop}"
        Header="Stop"
        Visibility="{Binding CanStop,
            Converter={StaticResource VisibleIfTrue}}"/>
</CompositeCollection>

最后是上下文菜单本身,也在ResourceDictionary中:

<ContextMenu 
    x:Key="FooButtonMenu"
    ItemsSource="{Binding Source={StaticResource FooListItems}}" 
    ItemTemplate="{StaticResource FooListTemplate}"
    <ContextMenu.CommandBindings>
        <CommandBinding  
                Command="{x:Static Buttons:FooButton.Stop}"
                Executed="Stop_Executed" />
    </ContextMenu.CommandBindings>
</ContextMenu>

我觉得我发布了许多代码的方式,但我不确定我是否可以使这篇文章变得更简单。仅显示分隔符和硬编码菜单项。所以必须搞清楚绑定的东西。绑定通常不是那么难,但是现在当我想要绑定一些不属于同一棵树的东西时,我觉得有点迷失。

欢迎任何建议。 :)

2 个答案:

答案 0 :(得分:1)

如您所料,您的问题似乎确实是由List<Foo>代替ObservableCollection<Foo>造成的。由于List<Foo>没有通知属性更改,因此让WPF识别您添加或删除项目的唯一方法是暂时将FooList属性设置为其他内容,然后将其重新设置。

无需切换到CLR属性。只需将List<Foo>更改为ObservableCollection<Foo>

CompositeCollection中的绑定不起作用的原因是CompositeCollection不是DependencyObject,因此它无法继承DataContext

答案 1 :(得分:0)

我不明白为什么你让FooList成为依赖属性。您不是将其作为绑定的目标,这是创建依赖项属性的最常见原因。您尚未实现回调,因此无法执行更改通知(创建依赖项属性的第二个最常见原因)。您没有将它用于值继承。那么,为什么呢?

在我看来,你真正想要的是FooListObservableCollection<Foo>类型的普通CLR属性(或任何实现INotifyCollectionChanged的类)。这将完成您需要的所有更改通知 - 至少,您需要的是您目前发布的代码。