ContextMenu使用MVVM在DataGrid中绑定源

时间:2009-09-03 15:33:25

标签: datagrid mvvm binding contextmenu

我有一个datagrid列,如下所示:

<toolkit:DataGridTemplateColumn>
                        <toolkit:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=LabelName}" Background="{Binding Path=Color}">
                                    <TextBlock.ContextMenu>
                                        <ContextMenu>
                                            <MenuItem x:Name="Assign" Header="Assign"
                                                      mvvm:CommandBehavior.Event="Click"
                                                      mvvm:CommandBehavior.Command="{Binding Path=DataContext.EditLabelCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}, AncestorLevel='1'}}"
                                                      mvvm:CommandBehavior.CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}"/>
                                        </ContextMenu>
                                    </TextBlock.ContextMenu>
                                </TextBlock>
                            </DataTemplate>
                        </toolkit:DataGridTemplateColumn.CellTemplate>

我正在尝试使用DataContext的EditLabelCommand,但我找不到绑定源。我该怎么做才能访问我的DataContext命令?

1 个答案:

答案 0 :(得分:3)

当您向下移动可视树时,DataContext会发生变化,a)将DataContext绑定到其他内容,或者b)使用类似于项控件(或者在您的情况下为网格)的内容,每个项目重复一次数据模板一个集合,为每个项目设置数据上下文。

在您的示例中,您的菜单项与TextBlock具有相同的DataContext。这将是绑定到数据网格每一行的对象。

根据您的代码,我认为您的整个UserControl的DataContext集中有一个EditLabelCommand。这可能是您绑定到网格的集合的父级。 (如果任何这些假设错误,请纠正我。)

如果是这种情况,您可以执行以下操作:

  • 您可以继续使用相对绑定。这很复杂而且错误 如您所见,倾向于易于重复使用您的数据 模板或其他XAML。我建议你避免使用这种技术。

  • 将命令保留在整个datacontext中的一种更简单的方法是使用 来自WPF Model-View-ViewModel Toolkit的CommandReference 。这个 允许您将该命令作为资源引用并使用资源绑定 访问它。像这样:

    <UserControl.Resources>
        <mvvmToolkit:CommandReference x:Key="EditLabelCommandReference" Command="{Binding EditLabelCommand}" />
    </UserControl.Resources>

    <!-- Your command binding then looks much simpler -->
    mvvm:CommandBehavior.Command="{StaticResource EditLabelCommandReference}"
  • 另一种(可能更好的)技术是重构以使用每行的MVVM模式。这样,您将在网格的每一行使用一个简单的ViewModel。这允许每一行保持自己的状态。因为您可以将Command实现移动到此ViewModel中,所以每行都有一个命令,无需传递参数。这样就可以一次编辑多个行的标签。 (如果这是一项要求。)