将ContextMenu绑定到Datagrid列

时间:2015-11-02 16:45:07

标签: c# wpf xaml datagrid

我正在尝试将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>

5 个答案:

答案 0 :(得分:3)

您应首先设置DataContext的{​​{1}},以便ItemsSource绑定到菜单项可以继承相同的DataContext。

ContextMenu

答案 1 :(得分:2)

ContextMenu无效但ComboBox起作用的原因是ContextMenuPopup,这意味着它不是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>