将 ContextMenu 的 DataContext 绑定到 containter 的 DataContext 中的属性



我有一个包含 ContentControlUserControlContentControl包含ContextMenu。我想将ContextMenuDataContext设置为UserControl的ViewModel中的属性。在这种情况下,该属性是另一个ViewModel。

以下是我的用户控制的.xAML:

<UserControl x:Class="TestProj.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:views="clr-namespace:OnyxWPF.Views"
             mc:Ignorable="d">
    <UserControl.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVis" />
    </UserControl.Resources>
    <Grid>
        <ContentControl Content="{Binding MainMap}">
            <ContentControl.ContextMenu>
                <ContextMenu DataContext="{Binding ContextMenuViewModel}" Visibility="{Binding IsPopUpEnabled, Converter={StaticResource BoolToVis}}" >
                    <MenuItem Header="Pan" Command="{Binding SetPanModeCmd}">
                        <MenuItem.Icon>
                            <Image Source="Images/panHand.ico" />
                        </MenuItem.Icon>
                    </MenuItem>
            </ContentControl.ContextMenu>
        </ContentControl>
    </Grid>
</UserControl>

这是用户控制背后的代码:

public partial class MainWindow : UserControl
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

MainViewModel-这是上述UserControlDataContext

public class MainViewModel
{
    public WpfMap MainMap { get; set; } //Content control's context is bound to this
    public ContextMenuViewModel ContextMenuViewModel { get; set; } //this should be the context menu's datacontext
    public bool IsPopUpEnabled { get; set; } //determines if the contextmenu will appear or not
    public MainViewModel()
    {
        MainMap = new WpfMap();
        ContextMenuViewModel = new ContextMenuViewModel();
        IsPopUpEnabled = true;
    }
}

最后,这是我的ConteactMenu的ViewModel:

public class ContextMenuViewModel
{
    public RelayCommand SetPanModeCmd { get; set; }
    public ContextMenuViewModel()
    {
        SetPanModeCmd = new RelayCommand(SetPanMode);
    }
    private void SetPanMode()
    {
        //stuff
    }
}

我在XAML中为上述ContextMenu所拥有的不起作用。我尝试使用RelativeSource尝试了一些不同的变化,但没有运气。我在下面尝试过的片段:

<ContextMenu DataContext="{Binding Path=Parent.DataContext.ContextMenuViewModel, RelativeSource={RelativeSource Self}}"
<ContextMenu DataContext="{Binding DataContext.ContextMenuViewModel, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
<ContextMenu DataContext="{Binding ContextMenuViewModel, RelativeSource={RelativeSource AncestorType=ContentControl}}"
<ContextMenu DataContext="{Binding DataContext.ContextMenuViewModel, RelativeSource={RelativeSource AncestorType=UserControl}}"

以上都没有工作。

来自Visual树的任何UIELENT都继承了父级的数据。在这种情况下,ContextMenu将MainViewModel作为DataContext将其分配给Parent ContentControl后。因此,这意味着您可以获取包括ContextMenuviewModel在内的MainViewModel的任何属性。顺便说一句,WPF数据绑定支持任意数量的嵌套属性。而您的XAML看起来像这样:

    <UserControl x:Class="TestProj.MainWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:views="clr-namespace:OnyxWPF.Views"
                 mc:Ignorable="d">
         <UserControl.Resources>
             <BooleanToVisibilityConverter x:Key="BoolToVis" />
         </UserControl.Resources>
         <Grid>
             <ContentControl Content="{Binding MainMap}">
                 <ContentControl.ContextMenu>
                     <ContextMenu Visibility="{Binding IsPopUpEnabled, Converter={StaticResource BoolToVis}}">
                         <MenuItem Header="Pan" 
                                   Command="{Binding ContextMenuViewModel.SetPanModeCmd}">
                             <MenuItem.Icon>
                                 <Image Source="Images/panHand.ico" />
                             </MenuItem.Icon>
                         </MenuItem>
                     </ContextMenu>
                 </ContentControl.ContextMenu>
             </ContentControl>
         </Grid>
     </UserControl>

P.S。为了澄清:Command="{Binding ContextMenuViewModel.SetPanModeCmd}"- CONTECTMENUVIEWMODEL是MainViewModel的属性的名称,而不是类型。

最新更新