0

我正在通过编程方式烹饪 DataGridTemplateColumns
DataTemplate dtStringTemplate = (DataTemplate)XamlReader.Load(sr, pc); dataGridTemplateColumn.CellTemplate = dtStringTemplate;

我尝试将 ContextMenu 添加到 DataGrid,但任何可编辑的单元格都使用了自己的上下文菜单。

到目前为止,这篇文章已经让我尽可能地让 TextBox 上下文菜单按预期出现:How to add a ContextMenu in the WPF DataGridColumn in MVVM?

使用上面提到的帖子作为指导,我在 App.xaml 中创建了 Style 和 ContextMenu;当我右键单击 DataGrid 中的单元格时,会出现我的上下文菜单。但是,我无法触发关联的命令,并且我怀疑绑定不正确。这是 App.xaml 中的 xaml:

<ContextMenu x:Key="DataGridContextMenu">
        <MenuItem Header="MenuItem One" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.CmdMenuItemOne}" />
        <MenuItem Header="MenuItem Two" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.CmdMenuItemOne}" />
    </ContextMenu>

DataGrid 的 DataContext 是 MyViewModel;MyViewModel 有一个名为 CmdMenuItemOne 的公共 DelegateCommand。
不幸的是,从未调用过 CmdMenuItemOne。
我对绑定有什么误解?谢谢 ...

4

2 回答 2

1

使用下面给出的非常简单的方法。

<Window.Resources>
    <FrameworkElement x:Key="DCKey" />
</Window.Resources>

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = vm;

        ((FrameworkElement)this.Resources["DCKey"]).DataContext = vm;
    }

<MenuItem Header="DoSomething" Command="{Binding DataContext.Cmd, Source={StaticResource DCKey}}"/>
于 2016-02-07T15:55:57.823 回答
0

由于 ContextMenu 不是 DataGrid 可视化树的一部分,因此我们无法访问 DataGrid 的 DataContext 中定义的属性。但是我们可以做下一个解决方法来做到这一点。

  1. 创建一个布尔附加属性来定义下一件事;如果添加的属性的值为true,它将找到该属性所附加到的对象的可视父级,并将父级的DataContext分配给该属性所附加到的对象的Tag属性,反之,如果值为附加属性为 false ,标签属性将被赋值为 null。
  2. 创建一个扩展帮助方法,它将扫描调用者的可视化树并返回它的(调用者)特定类型的父级。
  3. 为 DataGridCell 对象创建默认样式,该样式将使用上面描述的依赖属性并将定义 ContextMenu。将此样式设置为 App.xaml 中的资源(考虑到此样式将被项目中的所有 DataGridCell 对象使用)。

样式代码(应该在 App.xaml 中)

<Style TargetType="DataGridCell">
        <Setter Property="dataGridCreateColumnAndBindIteFromCodeBehind:DataGridAttached.SetDataGridDataContextToTag" Value="True"></Setter>
         <Setter Property="ContextMenu">
             <Setter.Value>
                <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="MenuItem One"
                              Command="{Binding CmdMenuItemOne}" />
                    <MenuItem Header="MenuItem Two" 
                              Command="{Binding CmdMenuItemTwo}" />
                </ContextMenu>
            </Setter.Value>
         </Setter></Style>

附属性代码

public class DataGridAttached
{

    public static readonly DependencyProperty SetDataGridDataContextToTagProperty = DependencyProperty.RegisterAttached(
        "SetDataGridDataContextToTag", typeof (bool), typeof (DataGridAttached), new PropertyMetadata(default(bool), SetParentDataContextToTagPropertyChangedCallback));

    public static void SetSetDataGridDataContextToTag(DependencyObject element, bool value)
    {
        element.SetValue(SetDataGridDataContextToTagProperty, value);
    }

    public static bool GetSetDataGridDataContextToTag(DependencyObject element)
    {
        return (bool) element.GetValue(SetDataGridDataContextToTagProperty);
    }

    private static void SetParentDataContextToTagPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        PerformDataContextToTagAssignment(dependencyObject as FrameworkElement, (bool)args.NewValue);
    }

    private static void PerformDataContextToTagAssignment(FrameworkElement sender, bool isAttaching)
    {
        var control = sender;
        if (control == null) return;
        if (isAttaching == false)
        {
            control.Tag = null;
        }
        else
        {
            var dataGrid = control.FindParent<DataGrid>();
            if (dataGrid == null) return;
            control.Tag = dataGrid.DataContext;
        }
    }
}

帮助代码

public static class VisualTreeHelperExtensions
{
    public static T FindParent<T>(this DependencyObject child) where T : DependencyObject
    {
        while (true)
        {
            //get parent item
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);

            //we've reached the end of the tree
            if (parentObject == null) return null;

            //check if the parent matches the type we're looking for
            T parent = parentObject as T;
            if (parent != null)
                return parent;
            child = parentObject;
        }
    }
}

问候。

于 2016-02-07T12:20:26.663 回答