Skip to content

Commit 1d8644d

Browse files
committed
Document SkinManager.
1 parent f8e0aa7 commit 1d8644d

File tree

8 files changed

+46
-10
lines changed

8 files changed

+46
-10
lines changed

.github/images/demo-winforms2.png

9.56 KB
Loading

.github/images/demo-wpf2.png

10.6 KB
Loading

DarkNet/DarkNet.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<PropertyGroup>
55
<TargetFrameworks>netcoreapp3.1;net452</TargetFrameworks>
6-
<Version>2.2.0-SNAPSHOT3</Version>
6+
<Version>2.2.0</Version>
77
<LangVersion>latest</LangVersion>
88
<Nullable>enable</Nullable>
99
<UseWindowsForms>true</UseWindowsForms>

DarkNet/WPF/SkinManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Linq;
44
using System.Windows;
55

6-
namespace Dark.Net.WPF;
6+
namespace Dark.Net.Wpf;
77

88
/// <summary>
99
/// Automatically swap the current WPF <see cref="Application"/> between a light and dark <see cref="ResourceDictionary"/> when the effective process theme changes between <see cref="Theme.Light"/>

Readme.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Enable native Windows dark mode for your WPF and Windows Forms title bars.
2121
- [On application startup](#on-application-startup)
2222
- [Before showing a new window](#before-showing-a-new-window)
2323
- [After showing a window](#after-showing-a-window)
24+
- [Client area](#client-area)
2425
- [Complete example](#complete-example)
2526
- [Windows Forms](#windows-forms)
2627
- [On application startup](#on-application-startup-1)
@@ -161,6 +162,35 @@ After calling `SetWindowThemeWpf` for the first time and showing a new window, y
161162

162163
Try the [demo apps](#demos) to see this behavior in action.
163164

165+
#### Client area
166+
167+
DarkNet does not give controls in the client area of your windows a dark skin. It only changes the theme of the title bar and system context menu. It is up to you to make the inside of your windows dark.
168+
169+
However, this library can help you switch your WPF application resource dictionaries to apply different styles when the process title bar theme changes. This requires you to create two resource dictionaries, one for the light theme and one for dark.
170+
171+
To tell DarkNet to switch between the resource dictionaries when the process theme changes, register them with [**`SkinManager`**](https://github.com/Aldaviva/DarkNet/blob/master/DarkNet/Wpf/SkinManager.cs):
172+
173+
```cs
174+
new Dark.Net.Wpf.SkinManager().RegisterSkins(
175+
lightThemeResources: new Uri("Skins/Skin.Light.xaml", UriKind.Relative),
176+
darkThemeResources: new Uri("Skins/Skin.Dark.xaml", UriKind.Relative));
177+
```
178+
179+
When you register the skin URIs, `SkinManager` will change the `Source` property of the merged resource dictionary to point to the correct skin, once when you call it and again whenever the current process theme changes in the future.
180+
181+
In your skin resource dictionaries, you can define resources, such as a `Color`, `Brush`, or `BitmapImage`, that are referred to using a `DynamicResource` binding somewhere in your window. You can also create a `Style` that applies to a `TargetType`, or that you refer to with a `DynamicResource`. These can apply a `ControlTemplate` to change the default appearance of controls like `CheckBox`, which unfortunately has property triggers that must be completely replaced in order to be restyled, instead of using template bindings or attached properties. Try to use `DynamicResource` instead of `StaticResource` so that the style can update when the skin is changed.
182+
183+
To get started overriding a control's default styles and control template, right-click the control in the Visual Studio XAML Designer, select Edit Template › Edit a Copy…, then define the resource in your skin's resource dictionary.
184+
185+
See [`darknet-demo-wpf`](https://github.com/Aldaviva/DarkNet/tree/master/darknet-demo-wpf) for an example.
186+
- [`Skins/`](https://github.com/Aldaviva/DarkNet/tree/master/darknet-demo-wpf/Skins) contains the resource dictionaries for [light](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/Skins/Skin.Light.xaml) and [dark](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/Skins/Skin.Dark.xaml) skins, as well as [common](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/Skins/Skin.Common.xaml) resources that are shared by both skins.
187+
- The dark skin in `Skin.Dark.xaml` overrides the styles and control template for the `CheckBox` to get rid of the light background, including when the mouse pointer is hovering over or clicking on it.
188+
- [`App.xaml.cs`](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/App.xaml.cs) registers the skins with `SkinManager`.
189+
- When referring to XAML files in other assemblies, or when processing assemblies with tools like [`ILRepack`](https://github.com/ravibpatel/ILRepack.Lib.MSBuild.Task), the skin URIs can change. You may need to [try multiple fallback URIs](https://github.com/Aldaviva/RemoteDesktopServicesCertificateSelector/blob/4beb7893ac99ef0a3bc512feb93398ea8993c9a6/RemoteDesktopServicesCertificateSelector/App.xaml.cs#L44-L59) depending on whether the app was built in a Debug or Release configuration.
190+
- [`App.xaml`](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/App.xaml) can optionally point to either the dark or light skin in its merged resource dictionary, which will be replaced at runtime by `SkinManager`. The value you set here is useful for previewing during Visual Studio XAML authoring. This merged dictionary can additionally refer to your other unrelated resource dictionaries and resources, which won't be touched by `SkinManager`.
191+
- [`MainWindow.xaml`](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/MainWindow.xaml) binds the `Window` `Style` property to a `DynamicResource` pointing to the `windowStyle` resource, which is defined twice in both the light and dark skin resource dictionaries. You need to explicitly bind `Window` styles like this instead of using a `TargetType` on your `Style` because `TargetType` does not apply to superclasses, and the concrete class here is `darknet_demo_wpf.MainWindow` instead of `System.Windows.Window`.
192+
193+
164194
#### Complete example
165195

166196
See the demo [`App.xaml.cs`](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/App.xaml.cs) and [`MainWindow.xaml.cs`](https://github.com/Aldaviva/DarkNet/blob/master/darknet-demo-wpf/MainWindow.xaml.cs).

darknet-demo-winforms/Form1.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ private void RenderTheme(bool isDarkTheme) {
2222
}
2323

2424
private void onDarkModeCheckboxChanged(object sender, EventArgs e) {
25-
DarkNet.Instance.SetCurrentProcessTheme(darkModeCheckbox.CheckState switch {
25+
Theme theme = darkModeCheckbox.CheckState switch {
2626
CheckState.Unchecked => Theme.Light,
2727
CheckState.Checked => Theme.Dark,
2828
CheckState.Indeterminate => Theme.Auto,
2929
_ => Theme.Auto
30-
});
30+
};
31+
DarkNet.Instance.SetCurrentProcessTheme(theme);
32+
Console.WriteLine($"Process theme is {theme}");
3133
}
3234

3335
}

darknet-demo-winforms/Program.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ private static void Main() {
1313
Application.EnableVisualStyles();
1414
Application.SetCompatibleTextRenderingDefault(false);
1515

16-
IDarkNet darkNet = DarkNet.Instance;
17-
darkNet.SetCurrentProcessTheme(Theme.Auto);
18-
19-
Form mainForm = new Form1();
20-
darkNet.SetWindowThemeForms(mainForm, Theme.Auto);
16+
IDarkNet darkNet = DarkNet.Instance;
17+
Theme processTheme = Theme.Auto;
18+
darkNet.SetCurrentProcessTheme(processTheme);
19+
Console.WriteLine($"Process theme is {processTheme}");
20+
21+
Form mainForm = new Form1();
22+
Theme windowTheme = Theme.Auto;
23+
darkNet.SetWindowThemeForms(mainForm, windowTheme);
24+
Console.WriteLine($"Window theme is {windowTheme}");
2125

2226
Console.WriteLine($"System theme is {(darkNet.UserDefaultAppThemeIsDark ? "Dark" : "Light")}");
2327
Console.WriteLine($"Taskbar theme is {(darkNet.UserTaskbarThemeIsDark ? "Dark" : "Light")}");

darknet-demo-wpf/App.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Windows;
33
using Dark.Net;
4-
using Dark.Net.WPF;
4+
using Dark.Net.Wpf;
55

66
namespace darknet_demo_wpf;
77

0 commit comments

Comments
 (0)