Вы получаете «Элемент уже является потомком другого элемента».исключение, потому что все элементы в TreeView имеют свой ContextMenus, связанный с одним и тем же объектом (ContextMenu, который вы определили в).
Вместо того, чтобы выставлять ContextMenu как свойство в MyControl, вы можете вместо этого выставить его HeirarchicalDataTemplate:
public HeirarchicalDataTemplate TreeViewItemTemplate {
get {
return (HeirarchicalDataTemplate)this.treeView.ItemTemplate;
}
set {
this.treeView.ItemTemplate = value;
}
}
Если вы решите пойти по этому пути, вам нужно будет определить TreeView ItemTemplate за пределами вашегооригинальный пользовательский контроль.Во внешнем клиенте, использующем UserControl, вы можете сделать это:
<my:MyControl>
<my:MyControl.TreeViewItemTemplate>
<Data:HierarchicalDataTemplate>
<!-- Rest of the template -->
<TextBlock x:Name="NameTextBlock" Text="{Binding Name}">
<controlsInputToolkit:ContextMenuService.ContextMenu>
<!-- ContextMenu -->
</controlsInputToolkit:ContextMenuService.ContextMenu>
<!-- Rest of the template -->
</Data:HierarchicalDataTemplate>
</my:MyControl.TreeViewItemTemplate>
</my:MyControl>
Подобные действия также увеличивают гибкость вашего UserControl как побочного эффекта, поскольку теперь вы можете настроить ItemTemplate TreeView в UserControl извне,Вы можете поместить HierarchicalDataTemplate в ResourceDictionary, если хотите последовательно использовать его.
Второе решение, если вы хотите использовать выделенный код, это просто использовать одно ContextMenu для всегоUserControl, а затем программно определить, какой элемент был выбран в коде для клиента.
<my:MyControl>
<my:MyControl.TreeViewItemTemplate>
<controlsInputToolkit:ContextMenuService.ContextMenu>
<!-- ContextMenu -->
</controlsInputToolkit:ContextMenuService.ContextMenu>
</my:MyControl.TreeViewItemTemplate>
</my:MyControl>