I want to create an application that does stuff in the background and is controllable via a Tray icon. This tray icon has a context menu with a checkbox that can be set to Enabled, and then the background task starts.
I am using WPF and the Hardcodet WPF NotifyIcon.
Here is my 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> Here is my Code Behind:
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 } } } } This does not work. I get the following in the output when running it:
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') The strange thing is: mainWindow IS found in the XAML editor when I type ElementName= for the IsChecked binding, as IntelliSense shows it to me.
What DOES work though is setting the DataContext programmatically in the Code-Behind right after InitializeComponent();:
DataContext = this; And then changing the binding to:
IsChecked="{Binding Enabled, UpdateSourceTrigger=PropertyChanged}" This does output the following:
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') but it works.
What am I doing wrong here? Or is setting the DataContext programmatically the way to go?
DataContext="{Binding RelativeSource={RelativeSource Self}}"in the opening<Window>tag and use the second, shorter binding.FindAncestormethod didn't work either, but the method I told about in my other comment works.