diff --git a/Source/Changelog.txt b/Source/Changelog.txt index 4d56c1a..81bf8aa 100644 --- a/Source/Changelog.txt +++ b/Source/Changelog.txt @@ -10,6 +10,10 @@ Contact and Information: http://www.hardcodet.net CHG DataContext is also assigned to ContextMenu, and properly coerced for ToolTips and Popups. Also checks whether target item has a binding on the DataContext (does not just override if DataContext is null). + Thanks Nic Pilllinger for pointing this one out. +CHG Popup creation no longer calls Popup.CreateRootPopup which tries to + bind to dependency properties that do not exist, thus causing debug + warnings. Thanks to Loic Berthollet for the hint. CHG The LeftClickCommand now executes with a delay in order to mak sure it's not a double-click. FIX Removed debug output in WindowMessageSink. diff --git a/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd b/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd index 42e21f9..e368a8f 100644 --- a/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd +++ b/Source/NotifyIconWpf/Diagrams/TaskbarIcon Overview.cd @@ -1,10 +1,10 @@  - + - + N6qdVIeUdLmQtSUbiJhEGdYRjvJYXlhbEVBDKuPRO5s= diff --git a/Source/NotifyIconWpf/TaskbarIcon.cs b/Source/NotifyIconWpf/TaskbarIcon.cs index 2a4ff06..875663f 100644 --- a/Source/NotifyIconWpf/TaskbarIcon.cs +++ b/Source/NotifyIconWpf/TaskbarIcon.cs @@ -196,7 +196,7 @@ namespace Hardcodet.Wpf.TaskbarNotification //events or override popup.PopupAnimation = animation; - Popup.CreateRootPopup(popup, balloon); + popup.Child = balloon; //don't set the PlacementTarget as it causes the popup to become hidden if the //TaskbarIcon's parent is hidden, too... @@ -589,9 +589,9 @@ namespace Hardcodet.Wpf.TaskbarNotification popup.PopupAnimation = PopupAnimation.None; //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); + //it tries to bind to "Popup-specific" properties in case they are provided by the child. + //We don't need that so just assign the control as the child. + popup.Child = TrayPopup; //do *not* set the placement target, as it causes the popup to become hidden if the //TaskbarIcon's parent is hidden, too. At runtime, the parent can be resolved through diff --git a/Source/Sample Project/Commands/CommandBase.cs b/Source/Sample Project/Commands/CommandBase.cs index 9b47695..e120a47 100644 --- a/Source/Sample Project/Commands/CommandBase.cs +++ b/Source/Sample Project/Commands/CommandBase.cs @@ -3,6 +3,8 @@ using System.ComponentModel; using System.Windows; using System.Windows.Input; using System.Windows.Markup; +using System.Windows.Media; +using Hardcodet.Wpf.TaskbarNotification; namespace Samples.Commands { @@ -73,5 +75,84 @@ namespace Samples.Commands .Metadata.DefaultValue; } } + + + /// + /// Resolves the window that owns the TaskbarIcon class. + /// + /// + /// + protected Window GetTaskbarWindow(object commandParameter) + { + if (IsDesignMode) return null; + + //get the showcase window off the taskbaricon + var tb = commandParameter as TaskbarIcon; + return tb == null ? null : TryFindParent(tb); + } + + + + #region TryFindParent helper + + /// + /// Finds a parent of a given item on the visual tree. + /// + /// The type of the queried item. + /// A direct or indirect child of the + /// queried item. + /// The first parent item that matches the submitted + /// type parameter. If not matching item can be found, a null + /// reference is being returned. + public static T TryFindParent(DependencyObject child) + where T : DependencyObject + { + //get parent item + DependencyObject parentObject = GetParentObject(child); + + //we've reached the end of the tree + if (parentObject == null) return null; + + //check if the parent matches the type we're looking for + T parent = parentObject as T; + if (parent != null) + { + return parent; + } + else + { + //use recursion to proceed with next level + return TryFindParent(parentObject); + } + } + + /// + /// This method is an alternative to WPF's + /// method, which also + /// supports content elements. Keep in mind that for content element, + /// this method falls back to the logical tree of the element! + /// + /// The item to be processed. + /// The submitted item's parent, if available. Otherwise + /// null. + public static DependencyObject GetParentObject(DependencyObject child) + { + if (child == null) return null; + ContentElement contentElement = child as ContentElement; + + if (contentElement != null) + { + DependencyObject parent = ContentOperations.GetParent(contentElement); + if (parent != null) return parent; + + FrameworkContentElement fce = contentElement as FrameworkContentElement; + return fce != null ? fce.Parent : null; + } + + //if it's not a ContentElement, rely on VisualTreeHelper + return VisualTreeHelper.GetParent(child); + } + + #endregion } } diff --git a/Source/Sample Project/Commands/HideMainWindowCommand.cs b/Source/Sample Project/Commands/HideSampleWindowCommand.cs similarity index 58% rename from Source/Sample Project/Commands/HideMainWindowCommand.cs rename to Source/Sample Project/Commands/HideSampleWindowCommand.cs index 694fb1f..d27cbcd 100644 --- a/Source/Sample Project/Commands/HideMainWindowCommand.cs +++ b/Source/Sample Project/Commands/HideSampleWindowCommand.cs @@ -6,19 +6,20 @@ namespace Samples.Commands /// /// Hides the main window. /// - public class HideMainWindowCommand : CommandBase + public class HideSampleWindowCommand : CommandBase { public override void Execute(object parameter) { - Application.Current.MainWindow.Hide(); + GetTaskbarWindow(parameter).Hide(); CommandManager.InvalidateRequerySuggested(); } public override bool CanExecute(object parameter) { - return !IsDesignMode && Application.Current.MainWindow.IsVisible; + Window win = GetTaskbarWindow(parameter); + return win != null && win.IsVisible; } diff --git a/Source/Sample Project/Commands/ShowMainWindowCommand.cs b/Source/Sample Project/Commands/ShowMainWindowCommand.cs deleted file mode 100644 index f3bccc9..0000000 --- a/Source/Sample Project/Commands/ShowMainWindowCommand.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Input; - -namespace Samples.Commands -{ - /// - /// Shows the main window. - /// - public class ShowMainWindowCommand : CommandBase - { - public override void Execute(object parameter) - { - Application.Current.MainWindow.Show(); - CommandManager.InvalidateRequerySuggested(); - } - - - public override bool CanExecute(object parameter) - { - return !IsDesignMode && Application.Current.MainWindow.IsVisible == false; - } - - } -} diff --git a/Source/Sample Project/Commands/ShowSampleWindowCommand.cs b/Source/Sample Project/Commands/ShowSampleWindowCommand.cs new file mode 100644 index 0000000..63a256a --- /dev/null +++ b/Source/Sample Project/Commands/ShowSampleWindowCommand.cs @@ -0,0 +1,24 @@ +using System.Windows; +using System.Windows.Input; + +namespace Samples.Commands +{ + /// + /// Shows the main window. + /// + public class ShowSampleWindowCommand : CommandBase + { + public override void Execute(object parameter) + { + GetTaskbarWindow(parameter).Show(); + CommandManager.InvalidateRequerySuggested(); + } + + + public override bool CanExecute(object parameter) + { + Window win = GetTaskbarWindow(parameter); + return win != null && !win.IsVisible; + } + } +} \ No newline at end of file diff --git a/Source/Sample Project/Main.xaml b/Source/Sample Project/Main.xaml index ffe00d0..a972bc9 100644 --- a/Source/Sample Project/Main.xaml +++ b/Source/Sample Project/Main.xaml @@ -3,8 +3,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Main" - Height="595" - Width="596" + Height="563" + Width="703" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> @@ -31,8 +31,7 @@ FontStyle="Italic" FontWeight="Bold" TextWrapping="Wrap"> + Text="WPF NotifyIcon 1.0.1 - Samples" /> - - - - \ No newline at end of file diff --git a/Source/Sample Project/Showcase/ShowcaseWindow.xaml b/Source/Sample Project/Showcase/ShowcaseWindow.xaml index bcaa51a..6d0e48e 100644 --- a/Source/Sample Project/Showcase/ShowcaseWindow.xaml +++ b/Source/Sample Project/Showcase/ShowcaseWindow.xaml @@ -70,7 +70,9 @@ Visibility="{Binding Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}, ElementName=iconVisibility, Mode=Default}" MenuActivation="{Binding Path=SelectedItem, ElementName=lstMenuTrigger, Mode=Default}" PopupActivation="{Binding Path=SelectedItem, ElementName=lstPopupTrigger, Mode=Default}" - DoubleClickCommand="{Commands:ShowMainWindowCommand}"> + DoubleClickCommand="{Commands:ShowSampleWindowCommand}" + DoubleClickCommandParameter="{Binding RelativeSource={RelativeSource Self}}" + > diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml index 1dd568b..00789fe 100644 --- a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml +++ b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml @@ -253,9 +253,7 @@ VerticalAlignment="Top" Height="31" TextWrapping="Wrap" - FontWeight="Bold"> + FontWeight="Bold"> \ No newline at end of file diff --git a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs index febb6e1..7562128 100644 --- a/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs +++ b/Source/Sample Project/Tutorials/07 - Events/EventVisualizerWindow.xaml.cs @@ -1,15 +1,4 @@ -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.Shapes; +using System.Windows; namespace Samples.Tutorials.Events { diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml index 1fb880d..1fec7a4 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml @@ -4,12 +4,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:tb="http://www.hardcodet.net/taskbar" Height="300" - Width="300"> + Width="500"> @@ -36,16 +36,19 @@ - + - + + + + + + diff --git a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs index a383e18..e21e133 100644 --- a/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs +++ b/Source/Sample Project/Tutorials/08 - DataBinding/DataBoundToolTipWindow.xaml.cs @@ -1,15 +1,4 @@ -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.Shapes; +using System.Windows; namespace Samples.Tutorials.DataBinding { @@ -27,9 +16,10 @@ namespace Samples.Tutorials.DataBinding protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { //clean up notifyicon (would otherwise stay open until application finishes) - MyNotifyIcon.Dispose(); + MyNotifyIcon1.Dispose(); + MyNotifyIcon2.Dispose(); base.OnClosing(e); } } -} +} \ No newline at end of file