如何将MenuItem.Header绑定到Window / UserControl依赖项属性? [英] How to bind MenuItem.Header to Window/UserControl dependency property?

查看:88
本文介绍了如何将MenuItem.Header绑定到Window / UserControl依赖项属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何将MenuItem.Header绑定到父Window / UserControl依赖项属性?这是一个简单的示例:

I`m wondering how can I bind MenuItem.Header to the parent Window/UserControl dependency property? Here is a simple example:

Window1.xaml

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" x:Name="self">
    <Grid>
        <Grid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="{Binding Path=MenuText, ElementName=self}" />
            </ContextMenu>
        </Grid.ContextMenu>
        <TextBlock Text="{Binding Path=MenuText, ElementName=self}"/>
    </Grid>
</Window>

Window1.xaml.cs

public partial class Window1 : Window {
    public static readonly DependencyProperty MenuTextProperty = DependencyProperty.Register(
        "MenuText", typeof (string), typeof (Window1), new PropertyMetadata("Item 1"));

    public Window1()
    {
        InitializeComponent();
    }

    public string MenuText {
        get { return (string)this.GetValue(MenuTextProperty); }
        set { this.SetValue(MenuTextProperty, value); }
    }
}

在我的情况下,文本块显示项目1 ,并且上下文菜单显示空白项目。我做错了什么?在我看来,我似乎对WPF数据绑定原则有严重的误解。

In my case, textblock displays "Item 1", and context menu displays empty item. What I`m doing wrong? It seems for me, that I faced serious misunderstaning of WPF databinding principles.

推荐答案

您应该在Visual的输出窗口中看到这一点。 Studio:

You should see this in the Output window of Visual Studio:


System.Windows.Data错误:4:
找不到引用
'ElementName进行绑定的源=自我'。
BindingExpression:Path = MenuText;
DataItem = null;目标元素是
‘MenuItem’(Name =’’);目标属性
是标题(类型为对象)

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=self'. BindingExpression:Path=MenuText; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Header' (type 'Object')

这是因为ContextMenu与VisualTree断开了连接,您需要以不同的方式进行此绑定。

That is because the ContextMenu is disconnected from the VisualTree, you need to do this Binding differently.

一种方法是通过 ContextMenu.PlacementTarget (应该是网格) ,则可以使用其DataContext建立绑定,例如:

One way is via ContextMenu.PlacementTarget (which should be the Grid), you could use its DataContext to establish a binding, e.g.:

<MenuItem Header="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext.MenuText}"/>

或在ContextMenu本身中设置DataContext:

or set up the DataContext in the ContextMenu itself:

<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}">
    <MenuItem Header="{Binding Path=MenuText}"/>
</ContextMenu>

如果这不是一个选项(因为网格的DataContext不能是Window / UserControl),可以尝试通过网格的 Tag 将引用传递给Window / UserControl。

If this is not an option (because the DataContext of the Grid cannot be the Window/UserControl) you can try to pass the reference to the Window/UserControl through the Tag of your Grid for example.

<Grid ...
      Tag="{x:Reference self}">
    <Grid.ContextMenu>
        <!-- The DataContext is now bound to PlacementTarget.Tag -->
        <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.Tag}">
            <MenuItem Header="{Binding Path=MenuText}"/>
        </ContextMenu>
    ...






注意:由于这种行为,我倾向于在 App.xaml 中定义一个助手样式,以使所有ContextMenu从其父级伪继承 DataContext:


As a side-note: Because of this behavior i tend to define a helper-style in App.xaml to make all ContextMenus "pseudo-inherit" the DataContext from their parent:

    <!-- Context Menu Helper -->
    <Style TargetType="{x:Type ContextMenu}">
        <Setter Property="DataContext" Value="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"/>
    </Style>

这篇关于如何将MenuItem.Header绑定到Window / UserControl依赖项属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆