我在复合集合中将命令绑定到menuitem时遇到问题。 MenuItem
是ContextMenu
的一部分,UserControl.Resources
中定义了<UserControl.Resources>
<ContextMenu x:Key="DataGridRowContextMenu">
<MenuItem Header=" Set label"/>
<MenuItem.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource labelsSelectSource}}" />
<MenuItem Header=" New label..."
Command="{Binding DataContext.NewLabel,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type UserControl}}}"/>
</CompositeCollection>
</MenuItem.ItemsSource>
</MenuItem>
<UserControl.Resources/>
。
问题是新标签的绑定无效。当我将MenuItem放在复合集合之外时,它将起作用。有什么想法吗?
{{1}}
答案 0 :(得分:1)
这是因为ContextMenu
与其包含父项不在同一visual tree
这一事实,导致数据绑定问题。由于ContextMenu
不在同一个可视树中,ElementName
,RelativeSouce
(FindAncestor
)等等绑定不起作用。
你可以通过
解决这个问题在UserControl背后的代码中:
NameScope.SetNameScope(DataGridRowContextMenu, NameScope.GetNameScope(this));
使用PlacementTarget
这样的属性 -
<ContextMenu
x:Key="DataGridRowContextMenu">
DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
.
.
.
<MenuItem
Header=" New label..."
Command="{Binding DataContext.NewLabel}"/>
或使用其他解决方案 -
答案 1 :(得分:1)
我一直在努力解决这个疯狂的ContextMenu及其MenuItems很长一段时间。但我发现了一个解决方案,可以使用名为“Data”的dependancyproperty创建自定义行为“BindingProxyBehaviour”。此属性包含一个对象,例如您的DataContext(如果您使用MVVM模式,则可能是您的ViewModel)。
public class BindingProxyDataBehavior : Freezable
{
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxyDataBehavior), new UIPropertyMetadata(null));
protected override Freezable CreateInstanceCore()
{
return new BindingProxyDataBehavior();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
}
只需在您的xaml文件中添加BindingProxy作为资源。
<UserControl.Resources>
<ResourceDictionary>
<behaviors:BindingProxyDataBehavior x:Key="BindingProxyViewModel" Data="{Binding}"/>
<behaviors:BindingProxyDataBehavior x:Key="BindingProxyViewModelDynamicDataList" Data="{Binding DynamicDataListObject}"/>
</ResourceDictionary>
</UserControl.Resources>
在我的情况下,我使用CompositeCollection来混合静态和动态MenuItems。因此第二个资源具有键“BindingProxyViewModelDynamicDataList”。
Voilà现在无论您的ContextMenu在哪里,您都可以轻松访问您的数据。 我的ContexMenu在xaml树中的位置是UserControl-&gt; Grid-&gt; DataGrid-&gt; DataGridTemplateColumn-&gt; CellTemplate-&gt; DataTemplate-&gt; TextBox.Template-&gt; Grid-&gt; TextBlock-&gt;控件:IconButton(简单customButton控件派生自button),这里我们在IconButton中:
<controls:IconButton.ContextMenu>
<ContextMenu x:Name="AnyContextMenuName">
<ContextMenu.Resources>
<HierarchicalDataTemplate DataType="{x:Type DynamicDataListItemType}">
<TextBlock Text="{Binding DynamicDataListItemProperty}"/>
</HierarchicalDataTemplate>
</ContextMenu.Resources>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource BindingProxyViewModelDynamicDataList}, Path=Data}"/>
<Separator/>
<MenuItem Header="Your static header" Command="{Binding Source={StaticResource BindingProxyViewModel}, Path=Data.ViewModelCommandForYourStaticMenuItem}"/>
</CompositeCollection>
</ContextMenu.ItemsSource>
<ContextMenu.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Foreground" Value="{DynamicResource DefaultForegroundBrush}"/>
<Setter Property="MenuItem.Command" Value="{Binding Source={StaticResource BindingProxyViewModel}, Path=Data.ViewModelCommandForDynamicMenuItems}"/>
<Setter Property="MenuItem.CommandParameter" Value="{Binding}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</controls:IconButton.ContextMenu>
我希望我能用这篇简短的文章来帮助你做个傻瓜。
答案 2 :(得分:0)
使用CommandTarget
属性或创建datacontext的staticRessource,如
<MenuItem Header=" New label..."
Command="{Binding Path=NewLabel,Source={StaticResource viewModel}}"/>