WPF的DataGrid:绑定的DataGridColumn知名度的ContextMenu的Menu

2019-07-23 03:52发布

我想控制DataGrid通过柱知名度ContextMenu通过右键单击列标题提供给用户。 该ContextMenu显示所有可用列的名称。 我使用的MVVM的设计模式。

我的问题是:我如何绑定DataGridColumnVisibility属性设置IsChecked一个物业MenuItem坐落在ContextMenu

一些样机代码:

<UserControl.Resources>         
    <ContextMenu x:Key="ColumnHeaderContextMenu">  
        <MenuItem Header="Menu Item..1" IsCheckable="True" />  
    </ContextMenu>  
    <Style x:Key="ColumnHeaderStyle" 
           TargetType="{x:Type toolkit:DataGridColumnHeader}">  
        <Setter Property="ContextMenu" 
                Value="{StaticResource ColumnHeaderContextMenu}" />  
    </Style>  
    <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />  
</UserControl.Resources>  

... FLAF FLAF FLAF

<toolkit:DataGrid x:Name="MyGrid" AutoGenerateColumns="False" 
    ItemsSource="{Binding MyCollection, Mode=Default}" 
    EnableColumnVirtualization="True" IsReadOnly="True" 
    ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">  
    <toolkit:DataGrid.Columns>  
        <toolkit:DataGridTextColumn Binding="{Binding Path=MyEntry}" 
            Header="MyEntry" Visibility="{Binding IsChecked, Converter=
                {StaticResource booleanToVisibilityConverter}.... />
    </toolkit:DataGrid.Columns>     
</toolkit:DataGrid>  

如果我是不清楚,请让我知道,我将试图阐述。

干杯,

Answer 1:

我只写了关于这一主题的博客文章。 它允许被显示,或通过一个ContextMenu通过右击任何列标题是可访问的隐藏DataGridColumns。 这个任务,因此是MVVM兼容通过附加属性纯粹的实现。

见博客文章



Answer 2:

我一直在寻找一个通用的 ,XAML(即,无代码隐藏),结合一个WPF DataGrid中列标题栏选择右键菜单的自动和简单的例子。 我看过成百上千的文章,但他们都不做完全正确的事情,或者他们没有通用不够。 所以,这就是我认为是最好的组合解决方案:

首先,把这些在资源字典。 我会离开它作为一个练习的读者写的可见性/布尔转换器,以确保复选框检查时,该列是可见的,反之亦然。 需要注意的是通过定义X:共享=“假”的上下文菜单中的资源,它会得到特定实例的状态,这意味着你可以使用这个单模板/资源为所有DataGrid的,他们都会保持自己的状态。

<Converters:VisiblityToInverseBooleanConverter x:Key="VisiblityToInverseBooleanConverter"/>

<ContextMenu x:Key="ColumnChooserMenu" x:Shared="False"
             DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" 
             ItemsSource="{Binding Columns, RelativeSource={RelativeSource AncestorType={x:Type sdk:DataGrid}}}">
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding Header}"/>
            <Setter Property="AutomationProperties.Name" Value="{Binding Header}"/>
            <Setter Property="IsCheckable" Value="True" />
            <Setter Property="IsChecked" Value="{Binding Visibility, Mode=TwoWay, Converter={StaticResource VisiblityToInverseBooleanConverter}}" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>

<Style x:Key="ColumnHeaderStyle" TargetType="{x:Type Primitives:DataGridColumnHeader}">
    <Setter Property="ContextMenu" Value="{StaticResource ColumnChooserMenu}" />
</Style>

<ContextMenu x:Key="GridItemsContextMenu" >
    <MenuItem Header="Launch Do Some other action"/>
</ContextMenu>

然后定义数据网格如下(其中OrdersQuery是由视图模型暴露了一些数据源):

<sdk:DataGrid ItemsSource="{Binding OrdersQuery}"
              AutoGenerateColumns="True" 
              ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
              ContextMenu="{StaticResource GridItemsContextMenu}">

  <!-- rest of datagrid stuff goes here -->

</sdk:DataGrid>

这会给你的情况如下:

  1. 绑定到其充当列选择的列标题的上下文菜单。
  2. 绑定到网格中的项目上下文菜单(执行对项目本身的动作 - 再次,动作的结合是读者的练习)。

希望这有助于谁一直在寻找这样一个例子人。



Answer 3:

我知道这是一个有点老。 但我一直在寻找这样做的,这篇文章是要简单得多: http://iimaginec.wordpress.com/2011/07/25/binding-wpf-toolkit%E2%80%99s-datagridcolumn-to-a-viewmodel- DataContext的-传播史换数据网格柱最MVVM路到互动与-的DataGridColumn /

所有你需要做的是设置的DataContext的列,然后绑定能见度到您的视图模型按照正常! :)简单有效



Answer 4:

好吧,这已经相当运动的WPF的n00b。

神经修复学感谢您的建议我使用了类似的形式给出,但它dosent带你一路。

以下是我想出了如果任何人都可以发现这样做的更加一致的方式,我将不胜感激任何意见:

阻碍:

  1. DataGridColumnHeader不支持上下文菜单。 因此,上下文菜单需要施加作为伴奏。

  2. 通过ContextMenu都有自己的DataContext,所以我们必须使用findancestor将其链接到的ViewModels datacontext的。

  3. ATM DataGrid控件不分析它的DataContext其列。 这可以在代码隐藏内容然而,我们使用的是MVVM模式,所以我决定追随jamiers方法

解:

放在Window.Resources的代码下面两个街区

    <Style x:Key="ColumnHeaderStyle"
           TargetType="{x:Type toolkit:DataGridColumnHeader}">
        <Setter Property="ContextMenu" 
                Value="{StaticResource ColumnHeaderContextMenu}" />
    </Style>  

    <ContextMenu x:Key="ColumnHeaderContextMenu">
        <MenuItem x:Name="MyMenuItem"
                  IsCheckable="True"
                  IsChecked="{Binding DataContext.IsHidden, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type toolkit:DataGrid}}}"/>
    </ContextMenu>

然后,数据网格看上去在XAML像这样

        <toolkit:DataGrid x:Name="MyGrid"
                          AutoGenerateColumns="False"
                          ItemsSource="{Binding SampleCollection, Mode=Default}"
                          EnableColumnVirtualization="True"
                          IsReadOnly="True"
                          ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">
            <toolkit:DataGrid.Columns>
                <toolkit:DataGridTextColumn Binding="{Binding Path=SamplingUser}"
                                            Header="{Binding (FrameworkElement.DataContext).IsHidden, RelativeSource={x:Static RelativeSource.Self}}"
                                            Visibility="{Binding (FrameworkElement.DataContext).IsHidden,
                                                RelativeSource={x:Static RelativeSource.Self},
                                                Converter={StaticResource booleanToVisibilityConverter}}"/>

因此,对的DataGridColumn visibility属性和ischeked属性均为数据绑定到视图模型中是否隐藏属性。

在视图模型:

    public bool IsHidden
    {
        get { return isHidden; }
        set 
        { if (value != isHidden)
            {
                isHidden = value;
                OnPropertyChanged("IsHidden");
                OnPropertyChanged("IsVisible");
            }
        }
    }  

通过Jaimer定义的Helper类:

class DataGridSupport
{
    static DataGridSupport() 
    {

        DependencyProperty dp = FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn)); 
        FrameworkElement.DataContextProperty.OverrideMetadata ( typeof(DataGrid), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged)));

    }

    public static void OnDataContextChanged ( DependencyObject d, DependencyPropertyChangedEventArgs e)
    { 
        DataGrid grid = d as DataGrid ; 
        if ( grid != null  ) 
        {                 
            foreach ( DataGridColumn col in grid.Columns ) 
            { 
                col.SetValue ( FrameworkElement.DataContextProperty,  e.NewValue ); 
            } 
        } 
    }
}

在视图模型实例化(只是为了显示团结,通过在实际项目中进行)

    private static DataGridSupport dc = new DataGridSupport();

干杯,



Answer 5:

相反booleanToVisibilityConverter你可以用x:静态

<Setter TargetName="UIElement"  Property="UIElement.Visibility" Value="x:Static Visibility.Hidden" />

在XAML静: http://msdn.microsoft.com/en-us/library/ms742135.aspx



Answer 6:

我曾尝试GE这种使用“的ElementName”绑定到文本菜单,但最后,得到它的工作在虚拟机,例如使用属性

bool _isHidden;
public bool IsHidden
{
  get { return _isHidden; }
  set
  {
    if (value != _isHidden)
    {
      _isHidden = value;
      RaisePropertyChanged("IsHidden");
      RaisePropertyChanged("IsVisible");
    }
  }
}

public Visibility IsVisible
{
  get { return IsHidden ? Visibility.Hidden : Visibility.Visible; }
}

而在XAML:

<Window.ContextMenu>
  <ContextMenu>
    <MenuItem Header="Hidden" IsCheckable="True" IsChecked="{Binding IsHidden}" />
  </ContextMenu>
</Window.ContextMenu>

<toolkit:DataGrid x:Name="MyGrid" AutoGenerateColumns="False" ItemsSource="{Binding MyCollection, Mode=Default}" EnableColumnVirtualization="True" IsReadOnly="True" ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">
  <toolkit:DataGrid.Columns>
    <toolkit:DataGridTextColumn Binding="{Binding Path=MyEntry}" Header="MyEntry" Visibility="{Binding Path=IsVisible, Mode=OneWay}" />
  </toolkit:DataGrid.Columns>
</toolkit:DataGrid>


文章来源: WPF DataGrid: Binding DataGridColumn visibility to ContextMenu MenuItems IsChecked (MVVM)