Данные, привязывающие свойство зависимости коллекции к меню в пользовательском элементе управления - PullRequest
1 голос
/ 27 июля 2011

У меня есть пользовательский элемент управления с собственным контекстным меню, однако мне нужно добавить дополнительные пункты в это меню.

Подход, который я выбрал, заключался в том, чтобы иметь свойство зависимостей под названием ContextMenuItems:

Public Shared ReadOnly ContextMenuItemsProperty As DependencyProperty = DependencyProperty.Register("ContextMenuItems", GetType(ObservableCollection(Of MenuItem)), GetType(SmartDataControl), New FrameworkPropertyMetadata(New ObservableCollection(Of MenuItem)))
Public Property ContextMenuItems As ObservableCollection(Of MenuItem)
    Get
        Return GetValue(ContextMenuItemsProperty)
    End Get

    Set(ByVal value As ObservableCollection(Of MenuItem))
        SetValue(ContextMenuItemsProperty, value)
    End Set
End Property

Затем я использовал CompositeCollection для объединения статических пунктов меню из элемента управления со списком, предоставленным хостом:

    <CompositeCollection x:Key="MenuItemsCompositeCollection">
        <MenuItem Header="TEST" />
        <CollectionContainer Collection="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ContextMenuItems, Converter={StaticResource TestConverter}}" />
        <MenuItem Header="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ContextMenuItems}" />
    </CompositeCollection>

Когда я связываюсь с этим ресурсом, я вижу:

  • ТЕСТ
  • (Коллекция)

Второй пункт меню привязан к коллекции, чтобы доказать, что я могу добраться до нее. У меня есть тестовый конвертер, который я добавил в пункт меню, и он ломается в методе конвертера, но когда я добавляю конвертер в CollectionContainer, он не вызывается.

Наконец, я получаю следующую ошибку в окне вывода:

System.Windows.Data Ошибка: 4: не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType =' System.Windows.Controls.UserControl ', AncestorLevel =' 1 ''. BindingExpression: Path = ContextMenuItems; DataItem = NULL; целевой элемент - CollectionContainer (HashCode = 41005040); Целевое свойство - «Коллекция» (тип «IEnumerable»)

1 Ответ

2 голосов
/ 27 июля 2011

Это ваше "доказательство" не работает, потому что два сравниваемых объекта явно не равны.Вы не можете использовать привязки RelativeSource или ElementName в контейнере коллекции, потому что необходимые условия не выполняются, т. Е. Нет NameScope и поскольку CollectionContainer является объектом абстракции, который не отображается ввизуальное дерево там также не является родительским, через которое можно найти предка.

Если у вас есть доступ к UserControl, вы можете использовать Binding.Source и x:Reference к имени UserControl, чтобы предотвратить ошибку циклической зависимости, CompositeCollection должен быть определен в UserControl.Resources и затем на него ссылаются, используя StaticResource.

например

<UserControl Name="control">
    <UserControl.Resources>
        <CompositeCollection x:Key="collection">
            <!-- ... -->
            <CollectionContainer Collection="{Binding ContextMenuItems, Source={x:Reference control}, Converter=...}"/>
        </CompositeCollection>
    </UserControl.Resources>
    <!-- ... -->
        <MenuItem ItemsSource="{Binding Source={StaticResource collection}}"/>
</UserControl>
...