Skip to content

Commit 961732b

Browse files
authored
Merge pull request #9461 from harshit7962/syncWindowResource
Sync Window Theme Mode with its Fluent Resource
2 parents f648cce + e65c17c commit 961732b

5 files changed

Lines changed: 79 additions & 4 deletions

File tree

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Application.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,7 +1752,7 @@ internal void InvalidateResourceReferences(ResourcesChangeInfo info)
17521752
if (!info.IsIndividualResourceChange
17531753
&& !ThemeManager.SkipAppThemeModeSyncing)
17541754
{
1755-
ThemeManager.SyncThemeMode();
1755+
ThemeManager.SyncApplicationThemeMode();
17561756
}
17571757

17581758
// Invalidate ResourceReference properties on all the windows.

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElement.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,8 @@ public ResourceDictionary Resources
707707
}
708708
set
709709
{
710+
bool invalidateResources = false;
711+
710712
ResourceDictionary oldValue = ResourcesField.GetValue(this);
711713
ResourcesField.SetValue(this, value);
712714

@@ -727,6 +729,11 @@ public ResourceDictionary Resources
727729
oldValue.RemoveOwner(this);
728730
}
729731

732+
if(this is Window window)
733+
{
734+
window.AddFluentDictionary(value, out invalidateResources);
735+
}
736+
730737
if (value != null)
731738
{
732739
if (!value.ContainsOwner(this))
@@ -743,7 +750,7 @@ public ResourceDictionary Resources
743750
// final invalidation & it is no worse than the old code that also did not invalidate in this case
744751
// Removed the not-empty check to allow invalidations in the case that the old dictionary
745752
// is replaced with a new empty dictionary
746-
if (oldValue != value)
753+
if (oldValue != value || invalidateResources)
747754
{
748755
TreeWalkHelper.InvalidateOnResourcesChange(this, null, new ResourcesChangeInfo(oldValue, value));
749756
}

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ThemeManager.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Standard;
22
using Microsoft.Win32;
33
using System.Collections;
4+
using System.Collections.ObjectModel;
45
using System.Collections.Generic;
56
using System.Windows.Interop;
67
using System.Windows.Media;
@@ -123,7 +124,7 @@ internal static void OnWindowThemeChanged(Window window, ThemeMode oldThemeMode,
123124
ApplyFluentOnWindow(window);
124125
}
125126

126-
internal static bool SyncThemeMode()
127+
internal static bool SyncApplicationThemeMode()
127128
{
128129
ThemeMode themeMode = GetThemeModeFromResourceDictionary(Application.Current.Resources);
129130

@@ -132,9 +133,20 @@ internal static bool SyncThemeMode()
132133
Application.Current.ThemeMode = themeMode;
133134
return themeMode == ThemeMode.None ? false : true;
134135
}
136+
135137
return false;
136138
}
137139

140+
internal static void SyncWindowThemeMode(Window window)
141+
{
142+
ThemeMode themeMode = GetThemeModeFromResourceDictionary(window.Resources);
143+
144+
if(window.ThemeMode != themeMode)
145+
{
146+
window.ThemeMode = themeMode;
147+
}
148+
}
149+
138150
internal static void ApplyStyleOnWindow(Window window)
139151
{
140152
if (!IsFluentThemeEnabled && window.ThemeMode == ThemeMode.None)
@@ -309,6 +321,8 @@ internal static bool IsFluentThemeEnabled
309321

310322
internal static bool SkipAppThemeModeSyncing { get; set; } = false;
311323

324+
internal static bool IgnoreWindowResourcesChange { get; set; } = false;
325+
312326
internal static double DefaultFluentThemeFontSize => 14;
313327

314328
internal static WindowCollection FluentEnabledWindows { get; set; } = new WindowCollection();
@@ -376,6 +390,8 @@ private static void AddOrUpdateThemeResources(ResourceDictionary rd, ResourceDic
376390

377391
int index = LastIndexOfFluentThemeDictionary(rd);
378392

393+
IgnoreWindowResourcesChange = true;
394+
379395
if (index >= 0)
380396
{
381397
rd.MergedDictionaries[index] = newDictionary;
@@ -384,6 +400,8 @@ private static void AddOrUpdateThemeResources(ResourceDictionary rd, ResourceDic
384400
{
385401
rd.MergedDictionaries.Insert(0, newDictionary);
386402
}
403+
404+
IgnoreWindowResourcesChange = false;
387405
}
388406

389407
private static int LastIndexOfFluentThemeDictionary(ResourceDictionary rd)

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TreeWalkHelper.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,17 @@ internal static void InvalidateOnResourcesChange(
457457
{
458458
Debug.Assert(fe != null || fce != null, "Node with the resources change notification must be an FE or an FCE.");
459459

460+
// Here we are syncing the window's Theme mode if resource dictionary changes.
461+
// The IgnoreWindowResourcesChange is a flag set to make sure the ThemeMode change does not cause an infinite loop of resource changes.
462+
if(fe is Window currentWindow)
463+
{
464+
currentWindow.AreResourcesInitialized = true;
465+
if(!ThemeManager.IgnoreWindowResourcesChange)
466+
{
467+
ThemeManager.SyncWindowThemeMode(currentWindow);
468+
}
469+
}
470+
460471
// We're interested in changes to the Template property that occur during
461472
// the walk - if the template has changed we don't need to invalidate
462473
// template-driven properties a second time. The HasTemplateChanged property

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,14 @@ public ThemeMode ThemeMode
583583
ThemeMode oldTheme = _themeMode;
584584
_themeMode = value;
585585

586+
if(!AreResourcesInitialized)
587+
{
588+
ThemeManager.OnWindowThemeChanged(this, oldTheme, value);
589+
AreResourcesInitialized = false;
590+
591+
_reloadFluentDictionary = true;
592+
}
593+
586594
if(IsSourceWindowNull)
587595
{
588596
_deferThemeLoading = true;
@@ -2120,6 +2128,22 @@ internal Point LogicalToDeviceUnits(Point ptLogicalUnits)
21202128
return ptDeviceUnits;
21212129
}
21222130

2131+
internal void AddFluentDictionary(ResourceDictionary value, out bool invalidateResources)
2132+
{
2133+
invalidateResources = false;
2134+
2135+
if(_reloadFluentDictionary && !AreResourcesInitialized)
2136+
{
2137+
if(value != null && ThemeMode != ThemeMode.None)
2138+
{
2139+
value.MergedDictionaries.Insert(0, ThemeManager.GetThemeDictionary(ThemeMode));
2140+
invalidateResources = true;
2141+
}
2142+
2143+
_reloadFluentDictionary = false;
2144+
}
2145+
}
2146+
21232147
internal static bool VisibilityToBool(Visibility v)
21242148
{
21252149
switch (v)
@@ -3282,6 +3306,19 @@ bool IWindowService.UserResized
32823306
{
32833307
get { return false; }
32843308
}
3309+
3310+
internal bool AreResourcesInitialized
3311+
{
3312+
get
3313+
{
3314+
return _resourcesInitialized;
3315+
}
3316+
set
3317+
{
3318+
_resourcesInitialized = value;
3319+
}
3320+
}
3321+
32853322
#endregion Internal Properties
32863323

32873324
//----------------------------------------------
@@ -7205,7 +7242,9 @@ private EventHandlerList Events
72057242

72067243
private SourceWindowHelper _swh; // object that will hold the window
72077244
private Window _ownerWindow; // owner window
7208-
7245+
private bool _reloadFluentDictionary = false;
7246+
private bool _resourcesInitialized = false;
7247+
72097248
// keeps track of the owner hwnd
72107249
// we need this one b/c a owner/parent
72117250
// can be set through the WindowInteropHandler

0 commit comments

Comments
 (0)