Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 找不到具有显式ElementName的WPF数据绑定_C#_Wpf_Xaml_Data Binding - Fatal编程技术网

C# 找不到具有显式ElementName的WPF数据绑定

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

我想创建一个应用程序,在后台做东西,并通过托盘图标控制。此托盘图标有一个上下文菜单,其中有一个复选框,可以设置为“已启用”,然后后台任务开始

我正在使用WPF和硬编码WPF通知图标

这是我的MainWindow.xaml:

<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}" ...>