ContextMenu上的DataContext绑定

时间:2018-02-05 14:32:51

标签: c# wpf xaml

我有DataGrid ContextMenu,我正在试图弄清楚如何正确绑定上下文。

到目前为止,我已经阅读了上下文菜单,它位于可视树之外,因此DataContext是不同的。考虑到这一点,提供的解决方案是使用属性Tag,但我仍然无法使其工作:

<UserControl>
    <!--#region DataGrid-->

    <DataGrid ItemsSource="{Binding Model.Collection}"
              Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}, Path=DataContext}">

        <!--#region Resources-->

        <DataGrid.Resources>

            <!--#region DataGridCell-->

            <Style TargetType="DataGridCell">

                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                            <MenuItem Header="Open Details"
                                      Command="{Binding DataContext.OpenRowDetailsCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                                      CommandParameter="{Binding DataContext.SelectedIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
                        </ContextMenu>
                    </Setter.Value>
                </Setter>

            </Style>

            <!--#endregion DataGridCell-->

        </DataGrid.Resources>

        <!--#endregion Resources-->

        <!--#region DataGridColumns-->

        <DataGrid.Columns>
            <DataGridTextColumn Header="Filename"
                                Binding="{Binding FileInfo.Name}"
                                Width="Auto" />
        </DataGrid.Columns>

        <!--#endregion DataGridColumns-->

    </DataGrid>

    <!--#endregion DataGrid-->

DataContext的{​​{1}}工作正常,因为我有其他使用UserControl的命令。

有人看到任何错误或有任何其他方法吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

如果OpenRowDetailsCommandSelectedIndex属性在父UserControl的视图模型类中定义,则此方法应该有效:

<Style TargetType="DataGridCell">
    <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" />
    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu>
                <MenuItem Header="Open Details"
                          Command="{Binding PlacementTarget.Tag.DataContext.OpenRowDetailsCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                          CommandParameter="{Binding PlacementTarget.Tag.DataContext.SelectedIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
            </ContextMenu>
        </Setter.Value>
    </Setter>
</Style>

答案 1 :(得分:0)

我喜欢使用BindingProxy(如this SO answer中所述)

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object),typeof(BindingProxy));
}

像这样使用:

<DataGrid ItemsSource="{Binding Model.Collection}">
    <DataGrid.Resources>
        <local:BindingProxy x:Key="VMProxy" Data="{Binding}" />
        <local:BindingProxy x:Key="DataGridProxy" Data="{Binding RelativeSource={RelativeSource Self}}" />
        <Style TargetType="DataGridCell">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem Header="Open Details"
                                  Command="{Binding Data.OpenRowDetailsCommand, Source={StaticResource VMProxy}}" 
                                  CommandParameter="{Binding Data.SelectedIndex, Source={StaticResource DataGridProxy}}"/>
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.Resources>