diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs index bb52d1c..d817b55 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs @@ -4,6 +4,7 @@ using System.Drawing; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; +using System.Windows.Input; using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification.Interop; @@ -207,7 +208,7 @@ namespace Hardcodet.Wpf.TaskbarNotification { ImageSource newValue = (ImageSource)e.NewValue; - //resolving the ImageSource at design time probably won't work + //resolving the ImageSource at design time is unlikely to work if (!Util.IsDesignMode) Icon = newValue.ToIcon(); } @@ -550,6 +551,169 @@ namespace Hardcodet.Wpf.TaskbarNotification #endregion + #region DataContext dependency property override + + /// + /// A static callback listener which is being invoked if the + /// dependency property has + /// been changed. Invokes the + /// instance method of the changed instance. + /// + /// The currently processed owner of the property. + /// Provides information about the updated property. + private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TaskbarIcon owner = (TaskbarIcon) d; + owner.OnDataContextPropertyChanged(e); + } + + + /// + /// Handles changes of the dependency property. As + /// WPF internally uses the dependency property system and bypasses the + /// property wrapper, updates of the property's value + /// should be handled here. + /// Provides information about the updated property. + private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) + { + object newValue = e.NewValue; + object oldValue = e.OldValue; + + //replace custom data context for popup and tooltip, if + //they are reflecting the data context's data context + var popup = TrayPopupResolved; + var toolTip = TrayToolTipResolved; + + if (popup != null && Equals(popup.DataContext, oldValue)) + { + popup.DataContext = newValue; + } + + if (toolTip != null && Equals(toolTip.DataContext, oldValue)) + { + toolTip.DataContext = newValue; + } + } + + #endregion + + + #region DoubleClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty DoubleClickCommandProperty = + DependencyProperty.Register("DoubleClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ public ICommand DoubleClickCommand + { + get { return (ICommand) GetValue(DoubleClickCommandProperty); } + set { SetValue(DoubleClickCommandProperty, value); } + } + + #endregion + + #region DoubleClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty DoubleClickCommandParameterProperty = + DependencyProperty.Register("DoubleClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ public object DoubleClickCommandParameter + { + get { return GetValue(DoubleClickCommandParameterProperty); } + set { SetValue(DoubleClickCommandParameterProperty, value); } + } + + #endregion + + #region LeftClickCommand dependency property + + /// + /// Associates a command that is being executed if the tray icon is being + /// double clicked. + /// + public static readonly DependencyProperty LeftClickCommandProperty = + DependencyProperty.Register("LeftClickCommand", + typeof (ICommand), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Associates a command that is being executed if the tray icon is being + /// double clicked. + ///
+ public ICommand LeftClickCommand + { + get { return (ICommand) GetValue(LeftClickCommandProperty); } + set { SetValue(LeftClickCommandProperty, value); } + } + + #endregion + + #region LeftClickCommandParameter dependency property + + /// + /// Command parameter for the . + /// + public static readonly DependencyProperty LeftClickCommandParameterProperty = + DependencyProperty.Register("LeftClickCommandParameter", + typeof (object), + typeof (TaskbarIcon), + new FrameworkPropertyMetadata(null)); + + /// + /// A property wrapper for the + /// dependency property:
+ /// Command parameter for the . + ///
+ public object LeftClickCommandParameter + { + get { return GetValue(LeftClickCommandParameterProperty); } + set { SetValue(LeftClickCommandParameterProperty, value); } + } + + #endregion + + /// + /// Executes a given command. + /// + /// The command to be executed. + /// An optional parameter that was associated with + /// the command. + private static void RunCommand(ICommand command, object commandParameter) + { + if (command == null) return; + if (command.CanExecute(commandParameter)) + { + command.Execute(commandParameter); + } + } + //EVENTS @@ -576,7 +740,10 @@ namespace Hardcodet.Wpf.TaskbarNotification /// protected RoutedEventArgs RaiseTrayLeftMouseDownEvent() { - return RaiseTrayLeftMouseDownEvent(this); + //first raise event, then command + RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this); + RunCommand(LeftClickCommand, LeftClickCommandParameter); + return args; } /// @@ -824,7 +991,9 @@ namespace Hardcodet.Wpf.TaskbarNotification /// protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent() { - return RaiseTrayMouseDoubleClickEvent(this); + RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this); + RunCommand(DoubleClickCommand, DoubleClickCommandParameter); + return args; } /// @@ -1515,6 +1684,11 @@ namespace Hardcodet.Wpf.TaskbarNotification //register change listener for the Visibility property PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged); VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md); + + //register change listener for the DataContext property + md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged)); + DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md); } + } } \ No newline at end of file diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 9a9a454..97bc38e 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -149,17 +149,24 @@ namespace Hardcodet.Wpf.TaskbarNotification CloseBalloon(); } + //create an invisible popup that hosts the UIElement Popup popup = new Popup(); popup.AllowsTransparency = true; + //provide the popup with the taskbar icon's data context + popup.DataContext = DataContext; + //don't animate by default - devs can use attached //events or override popup.PopupAnimation = animation; Popup.CreateRootPopup(popup, balloon); - popup.PlacementTarget = this; + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too... + //popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; popup.StaysOpen = true; @@ -332,10 +339,9 @@ namespace Hardcodet.Wpf.TaskbarNotification if (visible) { - if (ContextMenu != null && ContextMenu.IsOpen || - TrayPopupResolved != null && TrayPopupResolved.IsOpen) + if (IsPopupOpen) { - //ignore if we have an open context menu or popup + //ignore if we are already displaying something down there return; } @@ -389,7 +395,10 @@ namespace Hardcodet.Wpf.TaskbarNotification //create an invisible tooltip that hosts the UIElement tt = new ToolTip(); tt.Placement = PlacementMode.Mouse; - tt.PlacementTarget = this; + + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. + //tt.PlacementTarget = this; //the tooltip (and implicitly its context) explicitly gets //the DataContext of this instance. If there is no DataContext, @@ -484,7 +493,10 @@ namespace Hardcodet.Wpf.TaskbarNotification Popup.CreateRootPopup(popup, TrayPopup); - popup.PlacementTarget = this; + //TODO we don't really need this and it causes the popup to become hidden if the + //TaskbarIcon's parent is hidden, too. + //popup.PlacementTarget = this; + popup.Placement = PlacementMode.AbsolutePoint; popup.StaysOpen = false; } diff --git a/Source/Sample Project/FancyPopup.xaml b/Source/Sample Project/FancyPopup.xaml index 44c32ce..432b97e 100644 --- a/Source/Sample Project/FancyPopup.xaml +++ b/Source/Sample Project/FancyPopup.xaml @@ -72,6 +72,7 @@ Language="de-ch" />