簡體   English   中英

如何指定將ContextMenu添加到DataGridTemplateColumn的DataContext?

[英]How to specify a DataContext whet adding the ContextMenu to the DataGridTemplateColumn?

我正在通過編程方式烹飪DataGridTemplateColumns
DataTemplate dtStringTemplate = (DataTemplate)XamlReader.Load(sr, pc); dataGridTemplateColumn.CellTemplate = dtStringTemplate;

我嘗試將ContextMenu添加到DataGrid,但是所有可編輯的單元格都使用了自己的上下文菜單。

到目前為止,這篇文章使我遠不如預期的那樣顯示TextBox上下文菜單: 如何在MVVM的WPF DataGridColumn中添加ContextMenu?

以上述文章為指導,我在App.xaml中創建了Style和ContextMenu。 當我右鍵單擊DataGrid中的Cell時,將出現上下文菜單。 但是,我無法啟動關聯的命令,並且我懷疑綁定不正確。 這是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從未被調用。
我對綁定有什么誤解? 謝謝 ...

使用下面給出的非常簡單的方法。

<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}}"/>

由於ContextMenu不屬於DataGrid可視樹的一部分,因此我們無法訪問DataGrid的DataContext中定義的屬性。 但是我們可以執行下一個解決方法。

  1. 創建一個布爾值附加屬性來定義下一件事; 另一方面,如果add屬性的值為true,則將查找該屬性附加到的對象的可視父對象,並將父屬性的DataContext分配給該屬性附加到的對象的Tag屬性,如果附加屬性為false,則Tag屬性將分配為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;
        }
    }
}

問候。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM