diff --git a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
index d817b55..2870a7c 100644
--- a/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
+++ b/Source/NotifyIconWpf/TaskbarIcon.Declarations.cs
@@ -121,7 +121,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
}
///
- /// Provides a secure method for setting the CustomBalloon property.
+ /// Provides a secure method for setting the property.
///
/// The new value for the property.
protected void SetCustomBalloon(Popup value)
@@ -333,7 +333,21 @@ namespace Hardcodet.Wpf.TaskbarNotification
//recreate tooltip control
CreateCustomToolTip();
- //udpate tooltip settings - needed to make sure a string is set, even
+ if (e.OldValue != null)
+ {
+ //remove the taskbar icon reference from the previously used element
+ SetParentTaskbarIcon((DependencyObject) e.OldValue, this);
+ }
+
+
+ if (e.NewValue != null)
+ {
+ //set this taskbar icon as a reference to the new tooltip element
+ SetParentTaskbarIcon((DependencyObject) e.NewValue, this);
+ }
+
+
+ //update tooltip settings - needed to make sure a string is set, even
//if the ToolTipText property is not set. Otherwise, the event that
//triggers tooltip display is never fired.
WriteToolTipSettings();
@@ -390,6 +404,19 @@ namespace Hardcodet.Wpf.TaskbarNotification
/// Provides information about the updated property.
private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e)
{
+ if (e.OldValue != null)
+ {
+ //remove the taskbar icon reference from the previously used element
+ SetParentTaskbarIcon((DependencyObject)e.OldValue, this);
+ }
+
+
+ if (e.NewValue != null)
+ {
+ //set this taskbar icon as a reference to the new tooltip element
+ SetParentTaskbarIcon((DependencyObject)e.NewValue, this);
+ }
+
//create a pop
CreatePopup();
}
@@ -1670,7 +1697,38 @@ namespace Hardcodet.Wpf.TaskbarNotification
#endregion
-
+ //ATTACHED PROPERTIES
+
+ //TODO put into use
+ #region ParentTaskbarIcon
+
+ ///
+ /// An attached property that is assigned to
+ ///
+ public static readonly DependencyProperty ParentTaskbarIconProperty =
+ DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof (TaskbarIcon), typeof (TaskbarIcon));
+
+ ///
+ /// Gets the ParentTaskbarIcon property. This dependency property
+ /// indicates ....
+ ///
+ public static TaskbarIcon GetParentTaskbarIcon(DependencyObject d)
+ {
+ return (TaskbarIcon)d.GetValue(ParentTaskbarIconProperty);
+ }
+
+ ///
+ /// Sets the ParentTaskbarIcon property. This dependency property
+ /// indicates ....
+ ///
+ public static void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value)
+ {
+ d.SetValue(ParentTaskbarIconProperty, value);
+ }
+
+ #endregion
+
+
diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs
index 97bc38e..4021df0 100644
--- a/Source/NotifyIconWpf/TaskbarIcon.cs
+++ b/Source/NotifyIconWpf/TaskbarIcon.cs
@@ -163,7 +163,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
Popup.CreateRootPopup(popup, balloon);
- //TODO we don't really need this and it causes the popup to become hidden if the
+ //don't set the PlacementTarget as it causes the popup to become hidden if the
//TaskbarIcon's parent is hidden, too...
//popup.PlacementTarget = this;
@@ -180,6 +180,9 @@ namespace Hardcodet.Wpf.TaskbarNotification
SetCustomBalloon(popup);
}
+ //assign this instance as an attached property
+ SetParentTaskbarIcon(balloon, this);
+
//fire attached event
RaiseBalloonShowingEvent(balloon);
@@ -199,7 +202,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
///
/// Closes the current , if it's set.
///
- private void CloseBalloon()
+ public void CloseBalloon()
{
if (IsDisposed) return;
@@ -214,6 +217,11 @@ namespace Hardcodet.Wpf.TaskbarNotification
{
//if a balloon message is already displayed, close it immediately
popup.IsOpen = false;
+
+ //reset attached property
+ UIElement element = popup.Child;
+ if (element != null) SetParentTaskbarIcon(element, null);
+
SetCustomBalloon(null);
}
}
@@ -396,7 +404,7 @@ namespace Hardcodet.Wpf.TaskbarNotification
tt = new ToolTip();
tt.Placement = PlacementMode.Mouse;
- //TODO we don't really need this and it causes the popup to become hidden if the
+ //do *not* set the placement target, as it causes the popup to become hidden if the
//TaskbarIcon's parent is hidden, too.
//tt.PlacementTarget = this;
diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Source/Sample Project/Commands/CommandBase.cs
new file mode 100644
index 0000000..b3411ae
--- /dev/null
+++ b/Source/Sample Project/Commands/CommandBase.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Windows.Input;
+using System.Windows.Markup;
+
+namespace Sample_Project.Commands
+{
+ ///
+ /// Basic implementation of the
+ /// interface, which is also accessible as a markup
+ /// extension.
+ ///
+ public abstract class CommandBase : MarkupExtension, ICommand
+ where T : class, ICommand, new()
+ {
+ ///
+ /// A singleton instance.
+ ///
+ private static T command;
+
+ ///
+ /// Gets a shared command instance.
+ ///
+ public override object ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (command == null) command = new T();
+ return command;
+ }
+
+ ///
+ /// Fires when changes occur that affect whether
+ /// or not the command should execute.
+ ///
+ public event EventHandler CanExecuteChanged
+ {
+ add { CommandManager.RequerySuggested += value; }
+ remove { CommandManager.RequerySuggested -= value; }
+ }
+
+ ///
+ /// Defines the method to be called when the command is invoked.
+ ///
+ /// Data used by the command.
+ /// If the command does not require data to be passed,
+ /// this object can be set to null.
+ ///
+ public abstract void Execute(object parameter);
+
+ ///
+ /// Defines the method that determines whether the command
+ /// can execute in its current state.
+ ///
+ ///
+ /// This default implementation always returns true.
+ ///
+ /// Data used by the command.
+ /// If the command does not require data to be passed,
+ /// this object can be set to null.
+ ///
+ public virtual bool CanExecute(object parameter)
+ {
+ return true;
+ }
+ }
+}
diff --git a/Source/Sample Project/Commands/HideMainWindowCommand.cs b/Source/Sample Project/Commands/HideMainWindowCommand.cs
index c91b4b8..ea40b97 100644
--- a/Source/Sample Project/Commands/HideMainWindowCommand.cs
+++ b/Source/Sample Project/Commands/HideMainWindowCommand.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Windows;
+using System.Windows;
using System.Windows.Input;
namespace Sample_Project.Commands
@@ -10,30 +6,21 @@ namespace Sample_Project.Commands
///
/// Hides the main window.
///
- public class HideMainWindowCommand : ICommand
+ public class HideMainWindowCommand : CommandBase
{
- public event EventHandler CanExecuteChanged;
- public void Execute(object parameter)
+ public override void Execute(object parameter)
{
Application.Current.MainWindow.Hide();
- TaskbarIconCommands.RefreshCommands();
+ CommandManager.InvalidateRequerySuggested();
}
- public bool CanExecute(object parameter)
+ public override bool CanExecute(object parameter)
{
return Application.Current.MainWindow.IsVisible;
}
- ///
- /// Raises the event.
- ///
- internal void RaiseCanExcecuteChanged()
- {
- if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty);
- }
-
}
}
diff --git a/Source/Sample Project/Commands/ShowMainWindowCommand.cs b/Source/Sample Project/Commands/ShowMainWindowCommand.cs
index 8367ccf..d80e5ce 100644
--- a/Source/Sample Project/Commands/ShowMainWindowCommand.cs
+++ b/Source/Sample Project/Commands/ShowMainWindowCommand.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using System.Windows;
using System.Windows.Input;
@@ -10,29 +9,19 @@ namespace Sample_Project.Commands
///
/// Shows the main window.
///
- public class ShowMainWindowCommand : ICommand
+ public class ShowMainWindowCommand : CommandBase
{
- public event EventHandler CanExecuteChanged;
-
- public void Execute(object parameter)
+ public override void Execute(object parameter)
{
Application.Current.MainWindow.Show();
- TaskbarIconCommands.RefreshCommands();
+ CommandManager.InvalidateRequerySuggested();
}
- public bool CanExecute(object parameter)
+ public override bool CanExecute(object parameter)
{
return Application.Current.MainWindow.IsVisible == false;
}
- ///
- /// Raises the event.
- ///
- internal void RaiseCanExcecuteChanged()
- {
- if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty);
- }
-
}
}
diff --git a/Source/Sample Project/Commands/TaskbarIconCommands.cs b/Source/Sample Project/Commands/TaskbarIconCommands.cs
deleted file mode 100644
index abcd757..0000000
--- a/Source/Sample Project/Commands/TaskbarIconCommands.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Windows.Input;
-
-namespace Sample_Project.Commands
-{
- public static class TaskbarIconCommands
- {
- public static HideMainWindowCommand HideMain { get; set; }
- public static ShowMainWindowCommand ShowMain { get; set; }
-
-
- static TaskbarIconCommands()
- {
- HideMain = new HideMainWindowCommand();
- ShowMain =new ShowMainWindowCommand();
- }
-
- public static void RefreshCommands()
- {
- HideMain.RaiseCanExcecuteChanged();
- ShowMain.RaiseCanExcecuteChanged();
- }
- }
-}
diff --git a/Source/Sample Project/FancyBalloon.xaml b/Source/Sample Project/FancyBalloon.xaml
new file mode 100644
index 0000000..da723bb
--- /dev/null
+++ b/Source/Sample Project/FancyBalloon.xaml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Sample Project/FancyBalloon.xaml.cs b/Source/Sample Project/FancyBalloon.xaml.cs
new file mode 100644
index 0000000..ccda58e
--- /dev/null
+++ b/Source/Sample Project/FancyBalloon.xaml.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Hardcodet.Wpf.TaskbarNotification;
+
+namespace Sample_Project
+{
+ ///
+ /// Interaction logic for FancyBalloon.xaml
+ ///
+ public partial class FancyBalloon : UserControl
+ {
+ #region BalloonText dependency property
+
+ ///
+ /// Description
+ ///
+ public static readonly DependencyProperty BalloonTextProperty =
+ DependencyProperty.Register("BalloonText",
+ typeof (string),
+ typeof (FancyBalloon),
+ new FrameworkPropertyMetadata(""));
+
+ ///
+ /// A property wrapper for the
+ /// dependency property:
+ /// Description
+ ///
+ public string BalloonText
+ {
+ get { return (string) GetValue(BalloonTextProperty); }
+ set { SetValue(BalloonTextProperty, value); }
+ }
+
+ #endregion
+
+
+ public FancyBalloon()
+ {
+ InitializeComponent();
+ }
+
+
+ ///
+ /// Resolves the that displayed
+ /// the balloon and requests a close action.
+ ///
+ private void imgClose_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ //the tray icon assigned this attached property to simplify access
+ TaskbarIcon taskbarIcon = TaskbarIcon.GetParentTaskbarIcon(this);
+ taskbarIcon.CloseBalloon();
+ }
+ }
+}
diff --git a/Source/Sample Project/Sample Project.csproj b/Source/Sample Project/Sample Project.csproj
index 9f930c4..7d102c5 100644
--- a/Source/Sample Project/Sample Project.csproj
+++ b/Source/Sample Project/Sample Project.csproj
@@ -102,7 +102,7 @@
-
+
@@ -153,6 +153,9 @@
+
+
+
diff --git a/Source/Sample Project/TaskbarIconResources.xaml b/Source/Sample Project/TaskbarIconResources.xaml
index bb31716..7e6866d 100644
--- a/Source/Sample Project/TaskbarIconResources.xaml
+++ b/Source/Sample Project/TaskbarIconResources.xaml
@@ -31,7 +31,7 @@
x:Key="tbMenu">