Контекстное меню WPF привязано к свойству List <> зависимость - PullRequest
3 голосов
/ 17 марта 2010

Я пытаюсь сделать так, чтобы содержимое списка, свойство зависимостей которого отображалось в контекстном меню 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, мы также показываем разделитель и команду остановки. Эти привязки также не выполняются, хотя сами элементы MenuItem отображаются. Так что, если я смогу выяснить, почему они терпят неудачу, Список может быть проще.

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

1 голос
/ 18 марта 2010

Как вы и подозревали, ваша проблема, похоже, вызвана использованием List<Foo> вместо ObservableCollection<Foo>. Поскольку List<Foo> не уведомляет об изменениях свойств, единственный способ заставить WPF распознать, что вы добавили или удалили элемент, - временно установить для свойства FooList что-то другое, а затем установить его обратно.

Нет необходимости переключаться на свойство CLR. Просто измените List<Foo> на ObservableCollection<Foo>.

Причина, по которой привязки в вашем CompositeCollection не работают, заключается в том, что CompositeCollection не является объектом DependencyObject, поэтому он не может наследовать DataContext.

0 голосов
/ 17 марта 2010

Не понимаю, почему вы сделали FooList свойством зависимости. Вы не делаете это целью привязки, которая является наиболее распространенной причиной для создания свойства зависимости. Вы не реализовали обратный вызов, поэтому он не может сделать уведомление об изменении (вторая наиболее распространенная причина создания свойства зависимости). Вы не используете его для наследования значений. Так почему тогда?

Мне кажется, что вы действительно хотите, чтобы FooList было обычным свойством CLR типа ObservableCollection<Foo> (или любого класса, который реализует INotifyCollectionChanged). Это будет делать все уведомления об изменениях, которые вам нужны - по крайней мере, то, что вам нужно для кода, который вы опубликовали до сих пор.

...