From 7513b4d83a01ec25cfc62fc806888a777f6aa1e3 Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:42:03 +0800
Subject: [PATCH 01/12] fix: Fix system tray right-click menu not displaying
---
src/Wpf.Ui.Tray/Controls/NotifyIcon.cs | 36 +++++++++++++++++++++++---
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
index 32f1b2a6e..0b2091f2b 100644
--- a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
+++ b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
@@ -246,6 +246,9 @@ public NotifyIcon()
internalNotifyIconManager = new Wpf.Ui.Tray.Internal.InternalNotifyIconManager();
RegisterHandlers();
+
+ // Listen for DataContext changes to update ContextMenu
+ DataContextChanged += OnDataContextChanged;
}
///
@@ -363,6 +366,9 @@ protected virtual void Dispose(bool disposing)
System.Diagnostics.Debug.WriteLine($"INFO | {typeof(NotifyIcon)} disposed.", "Wpf.Ui.NotifyIcon");
+ // Clean up event handlers
+ DataContextChanged -= OnDataContextChanged;
+
Unregister();
internalNotifyIconManager.Dispose();
@@ -375,6 +381,13 @@ protected virtual void Dispose(bool disposing)
protected virtual void OnMenuChanged(ContextMenu contextMenu)
{
internalNotifyIconManager.ContextMenu = contextMenu;
+
+ // Set the DataContext for ContextMenu to enable binding
+ if (contextMenu.DataContext == null && DataContext != null)
+ {
+ contextMenu.DataContext = DataContext;
+ }
+
internalNotifyIconManager.ContextMenu.SetCurrentValue(Control.FontSizeProperty, MenuFontSize);
}
@@ -410,11 +423,11 @@ private static void OnFocusOnLeftClickChanged(DependencyObject d, DependencyProp
if (e.NewValue is not bool newValue)
{
notifyIcon.FocusOnLeftClick = false;
-
+ notifyIcon.internalNotifyIconManager.FocusOnLeftClick = false;
return;
}
- notifyIcon.FocusOnLeftClick = newValue;
+ notifyIcon.internalNotifyIconManager.FocusOnLeftClick = newValue;
}
private static void OnMenuOnRightClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -427,11 +440,11 @@ private static void OnMenuOnRightClickChanged(DependencyObject d, DependencyProp
if (e.NewValue is not bool newValue)
{
notifyIcon.MenuOnRightClick = false;
-
+ notifyIcon.internalNotifyIconManager.MenuOnRightClick = false;
return;
}
- notifyIcon.MenuOnRightClick = newValue;
+ notifyIcon.internalNotifyIconManager.MenuOnRightClick = newValue;
}
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -455,6 +468,12 @@ private void InitializeIcon()
internalNotifyIconManager.Icon = Icon;
internalNotifyIconManager.MenuOnRightClick = MenuOnRightClick;
internalNotifyIconManager.FocusOnLeftClick = FocusOnLeftClick;
+
+ // Add Menu initialization
+ if (Menu != null)
+ {
+ OnMenuChanged(Menu);
+ }
}
private void RegisterHandlers()
@@ -466,4 +485,13 @@ private void RegisterHandlers()
internalNotifyIconManager.MiddleClick += OnMiddleClick;
internalNotifyIconManager.MiddleDoubleClick += OnMiddleDoubleClick;
}
+
+ private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ // Update ContextMenu DataContext when NotifyIcon DataContext changes
+ if (Menu != null && e.NewValue != null)
+ {
+ Menu.DataContext = e.NewValue;
+ }
+ }
}
From f399109868373e46f8172be93b9c46b424f2d13b Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:42:36 +0800
Subject: [PATCH 02/12] fix: Fix system tray right-click menu not displaying
---
src/Wpf.Ui.Tray/Internal/InternalNotifyIconManager.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Wpf.Ui.Tray/Internal/InternalNotifyIconManager.cs b/src/Wpf.Ui.Tray/Internal/InternalNotifyIconManager.cs
index fdd299344..1f7d9267f 100644
--- a/src/Wpf.Ui.Tray/Internal/InternalNotifyIconManager.cs
+++ b/src/Wpf.Ui.Tray/Internal/InternalNotifyIconManager.cs
@@ -178,7 +178,10 @@ protected virtual void OpenMenu()
// Without setting the handler window at the front, menu may appear behind the taskbar
_ = Interop.User32.SetForegroundWindow(HookWindow.Handle);
- ContextMenuService.SetPlacement(ContextMenu, PlacementMode.MousePoint);
+
+ // Set placement properties for better positioning
+ ContextMenu.SetCurrentValue(ContextMenu.PlacementProperty, PlacementMode.MousePoint);
+ ContextMenu.SetCurrentValue(ContextMenu.PlacementTargetProperty, null);
// ContextMenu.ApplyMica();
ContextMenu.SetCurrentValue(ContextMenu.IsOpenProperty, true);
From 407812a608365855f832aed5f2582bce09cf758d Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:51:48 +0800
Subject: [PATCH 03/12] Update src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/Wpf.Ui.Tray/Controls/NotifyIcon.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
index 0b2091f2b..f74b94dfd 100644
--- a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
+++ b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
@@ -427,7 +427,7 @@ private static void OnFocusOnLeftClickChanged(DependencyObject d, DependencyProp
return;
}
- notifyIcon.internalNotifyIconManager.FocusOnLeftClick = newValue;
+ notifyIcon.FocusOnLeftClick = newValue;
}
private static void OnMenuOnRightClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
From c508dccc7a36d101e66b0ef55b0c01e4e449dc09 Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:51:57 +0800
Subject: [PATCH 04/12] Update src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/Wpf.Ui.Tray/Controls/NotifyIcon.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
index f74b94dfd..0b773ae82 100644
--- a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
+++ b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
@@ -440,7 +440,6 @@ private static void OnMenuOnRightClickChanged(DependencyObject d, DependencyProp
if (e.NewValue is not bool newValue)
{
notifyIcon.MenuOnRightClick = false;
- notifyIcon.internalNotifyIconManager.MenuOnRightClick = false;
return;
}
From 2227c4784549e36d0730e2c006d776f7cf1a1fcc Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:52:03 +0800
Subject: [PATCH 05/12] Update src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/Wpf.Ui.Tray/Controls/NotifyIcon.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
index 0b773ae82..940ed5fd6 100644
--- a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
+++ b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
@@ -443,7 +443,7 @@ private static void OnMenuOnRightClickChanged(DependencyObject d, DependencyProp
return;
}
- notifyIcon.internalNotifyIconManager.MenuOnRightClick = newValue;
+ notifyIcon.MenuOnRightClick = newValue;
}
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
From 49dfa3b1e8a1be312801e855ead743e6fa2f0916 Mon Sep 17 00:00:00 2001
From: Joe Du <13188169+joesdu@users.noreply.github.com>
Date: Fri, 25 Jul 2025 19:52:09 +0800
Subject: [PATCH 06/12] Update src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/Wpf.Ui.Tray/Controls/NotifyIcon.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
index 940ed5fd6..729fe56f7 100644
--- a/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
+++ b/src/Wpf.Ui.Tray/Controls/NotifyIcon.cs
@@ -423,7 +423,6 @@ private static void OnFocusOnLeftClickChanged(DependencyObject d, DependencyProp
if (e.NewValue is not bool newValue)
{
notifyIcon.FocusOnLeftClick = false;
- notifyIcon.internalNotifyIconManager.FocusOnLeftClick = false;
return;
}
From 366209b78d964054f8fe9ffd939d15c5cbd958f9 Mon Sep 17 00:00:00 2001
From: Joes
Date: Mon, 28 Jul 2025 12:01:14 +0800
Subject: [PATCH 07/12] feat: add tray menu demo
---
.../ViewModels/Windows/MainWindowViewModel.cs | 25 ++++-
.../Views/Windows/MainWindow.xaml.cs | 93 +++++++++++++++++++
2 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/src/Wpf.Ui.Gallery/ViewModels/Windows/MainWindowViewModel.cs b/src/Wpf.Ui.Gallery/ViewModels/Windows/MainWindowViewModel.cs
index 8132dd717..9edaa4c2f 100644
--- a/src/Wpf.Ui.Gallery/ViewModels/Windows/MainWindowViewModel.cs
+++ b/src/Wpf.Ui.Gallery/ViewModels/Windows/MainWindowViewModel.cs
@@ -63,7 +63,7 @@ public partial class MainWindowViewModel(IStringLocalizer localize
new NavigationViewItem(nameof(ThumbRate), typeof(ThumbRatePage)),
new NavigationViewItem(nameof(SplitButton), typeof(SplitButtonPage)),
new NavigationViewItem(nameof(Slider), typeof(SliderPage)),
- },
+ }
},
new NavigationViewItem
{
@@ -182,9 +182,26 @@ public partial class MainWindowViewModel(IStringLocalizer localize
];
[ObservableProperty]
- private ObservableCollection _trayMenuItems =
+ private ObservableCollection
private const string TemplateElementAutoSuggestBoxSymbolButton = "PART_AutoSuggestBoxSymbolButton";
+ ///
+ /// Template element represented by the PART_ContentScrollViewer name.
+ ///
+ private const string TemplateElementContentScrollViewer = "PART_ContentScrollViewer";
+
///
/// Gets or sets the control responsible for rendering the content.
///
@@ -93,6 +102,11 @@ public partial class NavigationView
///
protected System.Windows.Controls.Button? AutoSuggestBoxSymbolButton { get; set; }
+ ///
+ /// Gets or sets the that hosts the content of the .
+ ///
+ protected ScrollViewer? ContentScrollViewer { get; set; }
+
///
public override void OnApplyTemplate()
{
@@ -121,6 +135,11 @@ public override void OnApplyTemplate()
{
NavigationViewContentPresenter.Navigated -= OnNavigationViewContentPresenterNavigated;
NavigationViewContentPresenter.Navigated += OnNavigationViewContentPresenterNavigated;
+
+ // We need to wait for the NavigationViewContentPresenter to apply its template
+ // so we can find the ContentScrollViewer
+ NavigationViewContentPresenter.ApplyTemplate();
+ FindContentScrollViewer();
}
if (
@@ -151,6 +170,20 @@ is System.Windows.Controls.Button autoSuggestBoxSymbolButton
}
}
+ private void FindContentScrollViewer()
+ {
+ if (NavigationViewContentPresenter?.Template is null)
+ {
+ return;
+ }
+
+ // Try to find the ContentScrollViewer within the NavigationViewContentPresenter's template
+ if (NavigationViewContentPresenter.Template.FindName(TemplateElementContentScrollViewer, NavigationViewContentPresenter) is ScrollViewer scrollViewer)
+ {
+ ContentScrollViewer = scrollViewer;
+ }
+ }
+
protected T GetTemplateChild(string name)
where T : DependencyObject
{
diff --git a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.xaml b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.xaml
index b249c26c6..cb439ea76 100644
--- a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.xaml
+++ b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.xaml
@@ -1,4 +1,4 @@
-