找不到具有显式ElementName的WPF DataBinding

时间:2016-07-01 07:38:23

标签: c# wpf xaml data-binding

我想创建一个在后台执行操作并可通过Tray图标控制的应用程序。此托盘图标有一个上下文菜单,其复选框可以设置为“已启用”,然后启动后台任务。

我正在使用WPF和Hardcodet WPF NotifyIcon。

这是我的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>

这是我的代码背后:

using System;
using System.Windows;

namespace MyTrayApplication {
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        private bool _enabled;

        public MainWindow() {
            InitializeComponent();
        }

        private void exitItem_Click(object sender, RoutedEventArgs e) {
            Close();
        }

        private void configureItem_Click(object sender, RoutedEventArgs e) {
            // Code to fire up configuration
        }

        public bool Enabled {
            get {
                return _enabled;
            }
            set {
                _enabled = value;
                Console.WriteLine(value);
                // Code to enable the background task
            }
        }
    }
}

这不起作用。运行时我在输出中得到以下内容:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=mainWindow'. BindingExpression:Path=Enabled; DataItem=null; target element is 'MenuItem' (Name='enabledItem'); target property is 'IsChecked' (type 'Boolean')

奇怪的是:当我为mainWindow绑定输入ElementName=时,在XAML编辑器中找到了IsChecked IS ,因为IntelliSense向我展示了它。

DOES 的工作原理是在DataContext之后立即以编程方式设置InitializeComponent();

DataContext = this;

然后将绑定更改为:

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的方式?

3 个答案:

答案 0 :(得分:6)

您正在处理ContextMenu。这是最棘手的控件之一,因为它实际上是一个Window,它有自己的可视树。你必须想象底层是做类似的事情:

Window contextMenu = new Window();
contextMenu.Show();

这个窗口实例显然无法直接绑定到创建它的MainWindow,可以吗?

<强>装订

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

使用ElementName时,绑定引擎通常会忽略DataContext。它将开始在自己的可视树中查找具有特定名称的元素。就像我最初所说的那样,ContextMenu有自己的可视树,所以很明显它无法在其可视化树中找到该元素。

答案 1 :(得分:2)

这有点棘手。问题是ContextMenu不是可视树的一部分。请参阅此帖子以获取解决方案:WPF: Binding a ContextMenu to an MVVM Command

答案 2 :(得分:0)

元素名称区分大小写,您应该将其从“mainWindow”更新为“MainWindow”,因为绑定无法找到该元素,因为错误建议