rab*_*ens 3 c# data-binding wpf xaml
我想创建一个在后台执行操作的应用程序,并且可以通过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>
Run Code Online (Sandbox Code Playgroud)
这是我的代码背后:
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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用.运行时我在输出中得到以下内容:
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')
Run Code Online (Sandbox Code Playgroud)
奇怪的是:mainWindow
IS在XAML编辑发现当我输入ElementName=
的IsChecked
绑定,智能感知它显示给我.
什么DOES工作虽然是设置DataContext
在代码隐藏右后编程InitializeComponent();
:
DataContext = this;
Run Code Online (Sandbox Code Playgroud)
然后将绑定更改为:
IsChecked="{Binding Enabled, UpdateSourceTrigger=PropertyChanged}"
Run Code Online (Sandbox Code Playgroud)
这确实输出以下内容:
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')
Run Code Online (Sandbox Code Playgroud)
但它的确有效.
我在这做错了什么?或者以DataContext
编程方式设置要走的路?
你正在处理ContextMenu
.这是最棘手的控件之一,因为它实际上是一个Window,它有自己的可视树.你必须想象底层是做类似的事情:
Window contextMenu = new Window();
contextMenu.Show();
Run Code Online (Sandbox Code Playgroud)
这个窗口实例显然无法直接绑定到创建它的MainWindow,可以吗?
捆绑
ContextMenu本身就是一个独立的实体.默认情况下,它DataContext
与父(放置目标)隔离.幸运的是,ContextMenu具有PlacementTarget
属性,该属性自动成为您在XAML中放入的对象.
<SomeControl>
<SomeControl.ContextMenu>
<ContextMenu ....>
<!-- This ContextMenu's PlacementTarget is automatically SomeControl -->
<ContextMenu>
</SomeControl.ContextMenu>
</SomeControl>
Run Code Online (Sandbox Code Playgroud)
要进行绑定,您需要这样做:
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}" ...>
Run Code Online (Sandbox Code Playgroud)
对于您的情况,您使用的是一些外部API.显然,此自定义控件已将DataContext设置为其放置目标的DataContext.
您的问题是因为您的窗口的DataContext未设置为自己,您已经解决了.无论是xaml还是代码隐藏都同样有效.
的ElementName
使用时ElementName
,绑定引擎通常会忽略DataContext.它将开始在自己的可视树中查找具有特定名称的元素.就像我最初所说的那样,ContextMenu有自己的可视化树,显然它无法在其可视化树中找到该元素.
归档时间: |
|
查看次数: |
887 次 |
最近记录: |