如何将MenuItem.Header绑定到Window / UserControl依赖项属性? [英] How to bind MenuItem.Header to Window/UserControl dependency property?
问题描述
我想知道如何将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屋!