C# 找不到具有显式ElementName的WPF数据绑定
我想创建一个应用程序,在后台做东西,并通过托盘图标控制。此托盘图标有一个上下文菜单,其中有一个复选框,可以设置为“已启用”,然后后台任务开始 我正在使用WPF和硬编码WPF通知图标 这是我的MainWindow.xaml:C# 找不到具有显式ElementName的WPF数据绑定,c#,wpf,xaml,data-binding,C#,Wpf,Xaml,Data Binding,我想创建一个应用程序,在后台做东西,并通过托盘图标控制。此托盘图标有一个上下文菜单,其中有一个复选框,可以设置为“已启用”,然后后台任务开始 我正在使用WPF和硬编码WPF通知图标 这是我的MainWindow.xaml: <Window x:Name="mainWindow" x:Class="MyTrayApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presenta
<Window x:Name="mainWindow" x:Class="MyTrayApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyTrayApplication"
xmlns:tb="http://www.hardcodet.net/taskbar"
mc:Ignorable="d"
Title="MainWindow" Height="10" Width="10" Visibility="Hidden">
<tb:TaskbarIcon x:Name="taskbarIcon" IconSource="MyTrayApplication.ico" ToolTipText="My tray application" >
<tb:TaskbarIcon.ContextMenu>
<ContextMenu>
<MenuItem x:Name="enabledItem" Header="Enabled" IsCheckable="True" IsChecked="{Binding Path=Enabled, ElementName=mainWindow, UpdateSourceTrigger=PropertyChanged}"/>
<MenuItem x:Name="configureItem" Header="Configure..." Click="configureItem_Click"/>
<MenuItem x:Name="exitItem" Header="Exit" Click="exitItem_Click"/>
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
</tb:TaskbarIcon>
</Window>
奇怪的是:main窗口
是在XAML编辑器中找到的,当我为IsChecked
绑定键入ElementName=
时,正如IntelliSense向我显示的那样
但真正起作用的是在InitializeComponent()之后的代码隐藏中以编程方式设置DataContext
代码>:
然后将绑定更改为:
IsChecked="{Binding Enabled, UpdateSourceTrigger=PropertyChanged}"
这将输出以下内容:
System.Windows.Data Error: 40 : BindingExpression path error: 'Enabled' property not found on 'object' ''TaskbarIcon' (Name='taskbarIcon')'. BindingExpression:Path=Enabled; DataItem='TaskbarIcon' (Name='taskbarIcon'); target element is 'MenuItem' (Name='enabledItem'); target property is 'IsChecked' (type 'Boolean')
但它是有效的
我做错了什么?或者以编程方式设置DataContext
是一种方法吗?这有点棘手。问题是ContextMenu不是可视化树的一部分。有关解决方案,请参阅本文:您正在处理的ContextMenu
。这是需要处理的最棘手的控件之一,因为它实际上是一个独立的窗口,有自己的可视树。你必须想象底层正在做类似的事情:
Window contextMenu = new Window();
contextMenu.Show();
这个窗口实例显然不能直接绑定到创建它的主窗口,是吗
绑定
ContextMenu本身是一个单独的实体。默认情况下,其DataContext
与父对象(放置目标)隔离。幸运的是,ContextMenu有PlacementTarget
属性,它是您在XAML中自动放入的对象
<SomeControl>
<SomeControl.ContextMenu>
<ContextMenu ....>
<!-- This ContextMenu's PlacementTarget is automatically SomeControl -->
<ContextMenu>
</SomeControl.ContextMenu>
</SomeControl>
要进行绑定,您需要执行以下操作:
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}" ...>
对于您的情况,您正在使用一些外部API。显然,此自定义控件已将DataContext设置为其放置目标的DataContext
您的问题是因为您的窗口的DataContext没有设置为自身,您已经解决了这个问题。xaml或代码隐藏都同样有效
元素名称
使用ElementName
时,绑定引擎通常会忽略DataContext。它将开始在自己的可视化树中查找具有特定名称的元素。正如我最初所说的,ContextMenu有自己的可视树,因此显然它无法在其可视树中找到该元素。元素名称区分大小写,您应该将其从“MainWindow”更新为“MainWindow”,因为绑定无法找到该元素,正如错误提示的那样。也许您必须将其更改为“IsEnabled”不,我想检查一下,但我知道了。我必须在开头的
标记中设置DataContext=“{Binding RelativeSource={RelativeSource Self}}}”
,并使用第二个较短的绑定。很抱歉,我没有很好地阅读您的问题。我误解了。看起来,在您进行的第二次尝试中,“enabledItem”的DataContext在第一时间设置为TaskbarIcon而不是MainWindow是的,就是这样。奇怪的是,FindAncestor
方法也不起作用,但我在其他评论中提到的方法起作用了。
Window contextMenu = new Window();
contextMenu.Show();
<SomeControl>
<SomeControl.ContextMenu>
<ContextMenu ....>
<!-- This ContextMenu's PlacementTarget is automatically SomeControl -->
<ContextMenu>
</SomeControl.ContextMenu>
</SomeControl>
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}" ...>