DataGridRow的ContextMenuItems与DataGridRow本身之间的数据绑定如何与封装的Viewmodel中的属性一起工作?

时间:2017-02-14 00:46:37

标签: c# mvvm data-binding datagrid contextmenu

我知道我真的应该开始阅读一本关于XAML和WPF的书,因为我认为我的所有问题都属于对数据绑定的不了解(我多年来一直使用WinForms):

我的应用程序由TreeView和DataGrid组成。

在TreeView中,我为每个ParentNode添加了ViewModels,ChildNode为GrandChildNode。

我使用了Josh Smith found here的样本。

简而言之,他/我使用

<HierarchicalDataTemplate
                    DataType="{x:Type local:ViewModel.TreeViewChildNodeViewModel}"
                    ItemsSource="{Binding Children}"> 
</HierarchicalDataTemplate.Resources>

将ChildNode绑定到ChildNodeViewModel和相应的Model。

我添加 - 在TreeViewChildNodeViewModel构造函数中:

ContextMenuItems = new List<MenuItem>();
ContextMenuItems.Add(new MenuItem() {
                           Header = "Click",
                           Command = _cmdDoSmth
                           ToolTip = new ToolTip() { Content = "blabla" }
                                    }
);

使用此属性向View公开:

private readonly List<MenuItem> ContextMenuItems;
public List<MenuItem> ContextMenu {
    get { return ContextMenuItems; }
}

请注意,我有多个构造函数。我将不同的ContextMenuItem添加到ContextMenu列表,具体取决于我希望ViewModel使用的模型。 “root”ChildNode由a:

组成
<TextBlock
    Text="{Binding ChildNodeDisplayItem}">
    <TextBlock.ContextMenu>
        <ContextMenu
            ItemsSource="{Binding ContextMenu}"></ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

这应该是这样的。现在我的问题开始于尝试与datagrid做类似的事情。

我需要做的是:

我想在datagrid中显示行。每一行都有自己的Viewmodel,它有一个暴露的ContextMenuItem列表(当然还有模型)。我希望能够根据所选的视图模型定义每个上下文菜单的计数,标题和命令。

到目前为止我做了什么:

在我的MainWindow.xaml:

<Controls:MetroWindow.Resources>
    <ContextMenu  x:Key="DataRowContextMenu" ItemsSource="{Binding Path=ActionReactionDataGridViewModel/ContextMenu, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}"/>
</Controls:MetroWindow.Resources>

<DataGrid   
    AutoGenerateColumns="True"
    AutoGeneratingColumn="OnAutoGeneratingColumn"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Stretch"
    BorderThickness="1,1,1,1"
    Margin="0,0,0,0"
    ItemsSource="{Binding Path=ActionReactionDataGridViewModel/DataGridSource}"
    SelectedItem="{Binding Path=ActionReactionDataGridViewModel/SelectedDataGridItem}"
    BorderBrush="#FF020202">
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />              </Style>
    <DataGrid.RowStyle>
</DataGrid>

在我的MainWindowViewModel中:

    public MainWindowViewModel() // Constructor
    {
        actionReactionDataGrid = new ObservableCollection<ActionReactionDataGridViewModel>();
        actionReactionDataGrid.Add(new ActionReactionDataGridViewModel());

    }

    private ObservableCollection<ActionReactionDataGridViewModel> actionReactionDataGrid;
    public ObservableCollection<ActionReactionDataGridViewModel> ActionReactionDataGridViewModel 
    {
        get { return actionReactionDataGrid; }
    }

我的ActionReactionDataGridViewModel在这里:

    public class ActionReactionDataGridViewModel : ViewModelBase
{
    private readonly List<MenuItem> ContextMenuItems;

    public ActionReactionDataGridViewModel()
    {

        ContextMenuItems = new List<MenuItem>();

        ContextMenuItems.Add(new MenuItem()
                             {
                                Header = "blubb"
                             });

        dataGridSource = new ObservableCollection<ActionReactionDataGridModel>();
        dataGridSource.Add(new ActionReactionDataGridModel("Status","Eventname","Eventtyp","ReaktionName","ReaktionTyp"));
    }

    public List<MenuItem> ContextMenu {
        get { return ContextMenuItems; }
    }

    private ActionReactionDataGridModel selectedDataGridItem;
    public ActionReactionDataGridModel SelectedDataGridItem {
        get { return selectedDataGridItem; }
        set {selectedDataGridItem = value; RaisePropertyChanged("SelectedDataGridItem"); }
    }

    private ObservableCollection<ActionReactionDataGridModel> dataGridSource;
    public ObservableCollection<ActionReactionDataGridModel> DataGridSource {
        get { return dataGridSource; }
        set { dataGridSource = value; RaisePropertyChanged("DataGridSource"); }
    }


}

我认为发布模型的内容不是必需的,因为它只包含列标题和一些示例字符串。我认为我缺少的是告诉MainWindow.xaml中的View中的DataGrid控件将itemssource绑定到“DataGridSource”而不是“ActionReactionDataGridViewModel”。

我在SO上发现了关于将Context Menus添加到datagridrow的其他帖子。我缺少的是能够将计数,文本和命令绑定到每个视图模型。

非常感谢任何帮助。

谢谢。

//编辑1

确定。找出如何从viewmodel集合中传递viewmodel的属性很容易。

我添加了

ItemsSource="{Binding Path=ActionReactionDataGridViewModel/DataGridSource}

解释是here

现在我“只是”需要弄清楚如何将contextmenu项添加到每个viewmodel ......

1 个答案:

答案 0 :(得分:0)

<DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="HeaderName">
                    </MenuItem>
                </ContextMenu>
            </DataGrid.ContextMenu>

在内部菜单项中,您可以编写控件。