我正在尝试将DataGrid
列标题绑定到自己的ContextMenu
,如下所示:
<DataGrid x:Name="AllLogs">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Show/Hide Columns"
ItemsSource="{Binding ElementName=AllLogs, Path=Columns}">
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"></TextBlock>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
它总是在输出中发送以下错误:
找不到带参考的绑定源 '的ElementName = AllLogs'。 BindingExpression:路径=列; 的DataItem = NULL; target元素是'MenuItem'(Name ='');目标财产 是'ItemsSource'(输入'IEnumerable')
编辑:使用ComboBox
绑定按预期工作
<ComboBox ItemsSource="{Binding ElementName=AllLogs, Path=Columns}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Header}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
答案 0 :(得分:3)
您应首先设置DataContext
的{{1}},以便ItemsSource绑定到菜单项可以继承相同的DataContext。
ContextMenu
答案 1 :(得分:2)
ContextMenu
无效但ComboBox
起作用的原因是ContextMenu
是Popup
,这意味着它不是DataGrid
的一部分可视树,因此ElementName
不能像ComboBox
那样工作。实际上,@ user1672994与答案很接近。
<DataGrid x:Name="AllLogs">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Show/Hide Columns"
ItemsSource="{Binding PlacementTarget.Columns, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
答案 2 :(得分:1)
问题/误解是ContextMenu
不是视觉树的一部分。
因此ContextMenu.PlacementTarget
是您到可视化树中UIElement的“连接”,因此您必须通过PlacementTarget
来访问可视化树中的元素。
关于PlacementTarget
的MSDN:
将ContextMenu分配给FrameworkElement.ContextMenu时 或FrameworkContentElement.ContextMenu属性, ContextMenuService将此属性的此值更改为所有者 ContextMenu打开时显示FrameworkElement或FrameworkContentElement
在下面的答案中,您不必遍历搜索祖先类型,而是将UIElement用作DataContext
的{{1}}:
ContextMenu
答案 3 :(得分:0)
我不知道RadGrivView控件,但错误意味着它找不到名为&#34; Columns&#34;的IEnumerable属性。在你的元素上。您确定它是一个可公开访问的控件集合吗?
答案 4 :(得分:0)
ElementName使用VisualTree来查找所需的元素,它不是当前视觉树的一部分-与上下文菜单一样向上或向下,您将获得异常。
您可以使用不使用VisualTree的Binding Source = {x:Reference AllLogs},但是不幸的是,在您的用例中,如果直接使用不带样式的循环引用,则会获得循环引用的例外。
您需要使用的是RelativeSource绑定。
<Window.Resources>
<ContextMenu x:Key="headerMenu">
<ContextMenu.Items>
<MenuItem
Header="Show/Hide Columns"
ItemsSource="{Binding Columns, RelativeSource={RelativeSource AncestorType=DataGrid}}">
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</ContextMenu.Items>
</ContextMenu>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="ContextMenu" Value="{StaticResource headerMenu}" />
</Style>
</Window.Resources>
<Grid>
<DataGrid x:Name="AllLogs">
<DataGrid.Columns>
<DataGridTextColumn Header="ID"></DataGridTextColumn>
<DataGridTextColumn Header="Name"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
这也可以-参考:
<Window.Resources>
<ContextMenu x:Key="headerMenu">
<ContextMenu.Items>
<MenuItem
Header="Show/Hide Columns"
ItemsSource="{Binding Source={x:Reference AllLogs}, Path=Columns}">
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</ContextMenu.Items>
</ContextMenu>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="ContextMenu" Value="{StaticResource headerMenu}" />
</Style>
</Window.Resources>
<Grid>
<DataGrid x:Name="AllLogs">
<DataGrid.Columns>
<DataGridTextColumn Header="ID"></DataGridTextColumn>
<DataGridTextColumn Header="Name"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>