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 という名前の public 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 の場合、このプロパティがアタッチされているオブジェクトの視覚的な親を見つけ、このプロパティがアタッチされているオブジェクトの Tag プロパティに親の DataContext を割り当てます。添付プロパティが false の場合、Tag プロパティは null に割り当てられます。
  2. 呼び出し元のビジュアル ツリーをスキャンし、特定の型の (呼び出し元の) 親を返す拡張ヘルパー メソッドを作成します。
  3. 上記の依存関係プロパティを使用し、ContextMenu を定義する DataGridCell オブジェクトのデフォルト スタイルを作成します。このスタイルを 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 に答える