简体   繁体   English

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

[英]WPF context menu bound to List<> dependency property

Im trying to make the contents of a List thats a dependency property show up in a WPF context menu. 我试图使一个依赖属性列表的内容显示在WPF上下文菜单中。

I have a class with the following dependency property, a list of Foo's (data holding class): 我有一个具有以下依赖属性的类,一个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));

In XAML I set up the following static resource, I assume its needed since the context menu isnt part of the visual tree: 在XAML中我设置了以下静态资源,我认为它是必需的,因为上下文菜单不是可视化树的一部分:

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

        <!-- ... -->

    </ResourceDictionary>
</UserControl.Resources>

Also part of the ResourceDictionary above is a CompositeCollection which is needed to make the items show up in the actual context menu. 上面的ResourceDictionary的一部分是一个CompositeCollection,它需要使项目显示在实际的上下文菜单中。 If the UserControl CanStop property is true, we also show a separator and a stop command. 如果UserControl CanStop属性为true,我们还会显示分隔符和停止命令。 These bindings does also fail, although the MenuItems themselves show up. 虽然MenuItems本身出现,但这些绑定也会失败。 So If I can figure out why these fail, the List might be easier. 所以,如果我能弄清楚这些失败的原因,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>

And finally the context menu itself, also in the ResourceDictionary: 最后是上下文菜单本身,也在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>

I feel Im posting way to much code but Im not sure I can make this piece any simpler. 我觉得我发布了许多代码的方式,但我不确定我是否可以使这个更简单。 Only the separator and the hardcoded menuitem shows up. 仅显示分隔符和硬编码菜单项。 So something must be messed up with the bindings. 所以必须搞清楚绑定的东西。 Bindings are usually not that hard but now when I want to bind something thats not really part of the same tree I feel a bit lost. 绑定通常不是那么难,但现在当我想绑定一些不是同一棵树的东西时,我觉得有点迷失。

Any suggestions are welcome. 欢迎任何建议。 :) :)

As you suspected, your problem does seem to be caused by the use of List<Foo> instead of ObservableCollection<Foo> . 如您所料,您的问题似乎确实是由使用List<Foo>而不是ObservableCollection<Foo> Since List<Foo> doesn't notify on property changes, the only way to get WPF to recognize you've added or removed an item is to temporarily set the FooList property to something else and then set it back. 由于List<Foo>不会通知属性更改,因此让WPF识别您已添加或删除项目的唯一方法是暂时将FooList属性设置为其他内容,然后将其重新设置。

There is no need to switch to a CLR property. 无需切换到CLR属性。 Just change List<Foo> to ObservableCollection<Foo> . 只需将List<Foo>更改为ObservableCollection<Foo>

The reason the bindings in your CompositeCollection aren't working is that CompositeCollection is not a DependencyObject, so it can't inherit a DataContext . CompositeCollection中的绑定不起作用的原因是CompositeCollection不是DependencyObject,因此它不能继承DataContext

I don't see why you've made FooList a dependency property. 我不明白为什么你让FooList成为依赖属性。 You're not making it the target of a binding, which is the most common reason to create a dependency property. 您不是将其作为绑定的目标,这是创建依赖项属性的最常见原因。 You haven't implemented a callback, so it can't do change notification (the second most common reason to create a dependency property). 您尚未实现回调,因此无法执行更改通知(创建依赖项属性的第二个最常见原因)。 You're not using it for value inheritance. 您没有将它用于值继承。 So why, then? 那么为什么呢?

It seems to me that what you really want is for FooList to be a normal CLR property of type ObservableCollection<Foo> (or any class that implements INotifyCollectionChanged ). 在我看来,你真正想要的是FooListObservableCollection<Foo>类型的普通CLR属性(或任何实现INotifyCollectionChanged类)。 That will do all the change notification that you need - at least, that you need for the code you've posted so far. 这将完成您需要的所有更改通知 - 至少,您需要的是您目前发布的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM