diff --git a/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd b/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd
new file mode 100644
index 0000000..dc1f29e
--- /dev/null
+++ b/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+ N6qdVIeUdLmQtSUbiJhEGdYRjvJYXlhbEVBBKuPRO5s=
+ TaskbarIcon.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/NotifyIconWpf/Interop/TrayInfo.cs b/Source/NotifyIconWpf/Interop/TrayInfo.cs
index ded285b..34ea681 100644
--- a/Source/NotifyIconWpf/Interop/TrayInfo.cs
+++ b/Source/NotifyIconWpf/Interop/TrayInfo.cs
@@ -1,4 +1,4 @@
-// Interop code taken from Mike Marshall's AnyForm
+// Some interop code taken from Mike Marshall's AnyForm
using System;
using System.Drawing;
@@ -12,11 +12,10 @@ namespace Hardcodet.Wpf.TaskbarNotification.Interop
///
public static class TrayInfo
{
-
- [DllImport("user32.dll")]
- private static extern Int32 GetWindowLong(IntPtr hWnd, Int32 Offset);
-
-
+ ///
+ /// Gets the position of the system tray.
+ ///
+ /// Tray coordinates.
public static Point GetTrayLocation()
{
var info = new AppBarInfo();
diff --git a/Source/NotifyIconWpf/NotifyIconWpf.csproj b/Source/NotifyIconWpf/NotifyIconWpf.csproj
index 914b6b0..e7b3757 100644
--- a/Source/NotifyIconWpf/NotifyIconWpf.csproj
+++ b/Source/NotifyIconWpf/NotifyIconWpf.csproj
@@ -85,6 +85,7 @@
ResXFileCodeGenerator
Resources.Designer.cs
+
SettingsSingleFileGenerator
Settings.Designer.cs
diff --git a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs
index df1277c..e49731a 100644
--- a/Source/NotifyIconWpf/Properties/AssemblyInfo.cs
+++ b/Source/NotifyIconWpf/Properties/AssemblyInfo.cs
@@ -53,5 +53,5 @@ using System.Windows.Markup;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.0.1.0")]
+[assembly: AssemblyFileVersion("1.0.1.0")]
diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
index 22fe1d5..0166c6a 100644
--- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
+++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
@@ -557,7 +557,24 @@ namespace Hardcodet.Wpf.TaskbarNotification
#endregion
- #region DataContext dependency property override
+ #region DataContext dependency property override / target update
+
+ ///
+ /// Updates the of a given
+ /// . This method only updates target elements
+ /// that do not already have a data context of their own, and either assigns
+ /// the of the NotifyIcon, or the
+ /// NotifyIcon itself, if no data context was assigned at all.
+ ///
+ private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue)
+ {
+ if (target != null && !target.IsDataContextDataBound() && Equals(oldDataContextValue, target.DataContext))
+ {
+ //assign own data context, if available. If there is no data
+ //context at all, assign NotifyIcon itself.
+ target.DataContext = newDataContextValue ?? this;
+ }
+ }
///
/// A static callback listener which is being invoked if the
@@ -586,24 +603,58 @@ namespace Hardcodet.Wpf.TaskbarNotification
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;
- }
+ //replace custom data context for ToolTips, Popup, and
+ //ContextMenu
+ UpdateDataContext(TrayPopupResolved, oldValue, newValue);
+ UpdateDataContext(TrayToolTipResolved, oldValue, newValue);
+ UpdateDataContext(ContextMenu, oldValue, newValue);
}
#endregion
+ #region ContextMenu 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 ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TaskbarIcon owner = (TaskbarIcon)d;
+ owner.OnContextMenuPropertyChanged(e);
+ }
+
+
+ ///
+ /// Releases the old and updates the new property
+ /// in order to reflect both the NotifyIcon's
+ /// property and have the assigned.
+ ///
+ /// Provides information about the updated property.
+ private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e)
+ {
+ if (e.OldValue != null)
+ {
+ //remove the taskbar icon reference from the previously used element
+ SetParentTaskbarIcon((DependencyObject)e.OldValue, null);
+ }
+
+ if (e.NewValue != null)
+ {
+ //set this taskbar icon as a reference to the new tooltip element
+ SetParentTaskbarIcon((DependencyObject)e.NewValue, this);
+ }
+
+ UpdateDataContext((ContextMenu) e.NewValue, null, DataContext);
+ }
+
+ #endregion
+
+
#region DoubleClickCommand dependency property
@@ -1752,7 +1803,12 @@ namespace Hardcodet.Wpf.TaskbarNotification
//register change listener for the DataContext property
md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged));
DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md);
+
+ //register change listener for the ContextMenu property
+ md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged));
+ ContextMenuProperty.OverrideMetadata(typeof(TaskbarIcon), md);
}
+
}
}
\ No newline at end of file
diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs
index dd8405a..cd3afa4 100644
--- a/Source/NotifyIconWpf/TaskbarIcon.cs
+++ b/Source/NotifyIconWpf/TaskbarIcon.cs
@@ -30,6 +30,7 @@ using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
+using System.Windows.Data;
using System.Windows.Threading;
using Hardcodet.Wpf.TaskbarNotification.Interop;
using Point=Hardcodet.Wpf.TaskbarNotification.Interop.Point;
@@ -182,14 +183,13 @@ 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;
+ UpdateDataContext(popup, null, DataContext);
//don't animate by default - devs can use attached
//events or override
@@ -314,8 +314,6 @@ namespace Hardcodet.Wpf.TaskbarNotification
#endregion
-
-
#region Process Incoming Mouse Events
///
@@ -483,11 +481,6 @@ namespace Hardcodet.Wpf.TaskbarNotification
//the ParentTaskbarIcon attached dependency property:
//tt.PlacementTarget = this;
- //the tooltip (and implicitly its context) explicitly gets
- //the DataContext of this instance. If there is no DataContext,
- //the TaskbarIcon sets itself
- tt.DataContext = DataContext ?? this;
-
//make sure the tooltip is invisible
tt.HasDropShadow = false;
tt.BorderThickness = new Thickness(0);
@@ -504,6 +497,13 @@ namespace Hardcodet.Wpf.TaskbarNotification
tt.Content = ToolTipText;
}
+ //the tooltip explicitly gets the DataContext of this instance.
+ //If there is no DataContext, the TaskbarIcon assigns itself
+ if (tt != null)
+ {
+ UpdateDataContext(tt, null, DataContext);
+ }
+
//store a reference to the used tooltip
SetTrayToolTipResolved(tt);
}
@@ -566,11 +566,9 @@ namespace Hardcodet.Wpf.TaskbarNotification
//events or override
popup.PopupAnimation = PopupAnimation.None;
- //the tooltip (and implicitly its context) explicitly gets
- //the DataContext of this instance. If there is no DataContext,
- //the TaskbarIcon assigns itself
- popup.DataContext = DataContext ?? this;
-
+ //the CreateRootPopup method outputs binding errors in the debug window because
+ //it tries to bind to "Popup-specific" properties in case they are provided by the child
+ //not a problem.
Popup.CreateRootPopup(popup, TrayPopup);
//do *not* set the placement target, as it causes the popup to become hidden if the
@@ -582,6 +580,13 @@ namespace Hardcodet.Wpf.TaskbarNotification
popup.StaysOpen = false;
}
+ //the popup explicitly gets the DataContext of this instance.
+ //If there is no DataContext, the TaskbarIcon assigns itself
+ if (popup != null)
+ {
+ UpdateDataContext(popup, null, DataContext);
+ }
+
//store a reference to the used tooltip
SetTrayPopupResolved(popup);
}
diff --git a/Source/NotifyIconWpf/Util.cs b/Source/NotifyIconWpf/Util.cs
index 8691996..c7ef9f6 100644
--- a/Source/NotifyIconWpf/Util.cs
+++ b/Source/NotifyIconWpf/Util.cs
@@ -27,6 +27,7 @@ using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows;
+using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Resources;
@@ -99,9 +100,10 @@ namespace Hardcodet.Wpf.TaskbarNotification
/// Updates the taskbar icons with data provided by a given
/// instance.
///
- ///
- ///
- ///
+ /// Configuration settings for the NotifyIcon.
+ /// Operation on the icon (e.g. delete the icon).
+ /// True if the data was successfully written.
+ /// See Shell_NotifyIcon documentation on MSDN for details.
public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command)
{
return WriteIconData(ref data, command, data.ValidMembers);
@@ -112,10 +114,12 @@ namespace Hardcodet.Wpf.TaskbarNotification
/// Updates the taskbar icons with data provided by a given
/// instance.
///
- ///
- ///
- ///
- ///
+ /// Configuration settings for the NotifyIcon.
+ /// Operation on the icon (e.g. delete the icon).
+ /// Defines which members of the
+ /// structure are set.
+ /// True if the data was successfully written.
+ /// See Shell_NotifyIcon documentation on MSDN for details.
public static bool WriteIconData(ref NotifyIconData data, NotifyCommand command, IconDataMembers flags)
{
//do nothing if in design mode
@@ -270,5 +274,21 @@ namespace Hardcodet.Wpf.TaskbarNotification
#endregion
+
+ ///
+ /// Checks whether the
+ /// is bound or not.
+ ///
+ /// The element to be checked.
+ /// True if the data context property is being managed by a
+ /// binding expression.
+ /// If
+ /// is a null reference.
+ public static bool IsDataContextDataBound(this FrameworkElement element)
+ {
+ if (element == null) throw new ArgumentNullException("element");
+ return element.GetBindingExpression(FrameworkElement.DataContextProperty) != null;
+ }
+
}
}