diff --git a/appveyor.yml b/appveyor.yml
index 9f20981bca..f3dd285dc5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,6 +6,8 @@ branches:
- main
environment:
+ # bad, but without this, gitversion doesn't work anymore
+ IGNORE_NORMALISATION_GIT_HEAD_MOVE: 1
azure-key-vault-url:
secure: 1mKS/HfCVq+iYNRVSrrN8NEowOkKt3knrpMzw+SOy3g=
azure-key-vault-client-id:
@@ -30,7 +32,7 @@ install:
git checkout -qf $($env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT)
}
- ps: Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile 'dotnet-install.ps1'
- - ps: ./dotnet-install.ps1 -Version 8.0.100 -InstallDir "C:\Program Files\dotnet"
+ - ps: ./dotnet-install.ps1 -Version 8.0.403 -InstallDir "C:\Program Files\dotnet"
pull_requests:
do_not_increment_build_number: false
@@ -38,7 +40,7 @@ pull_requests:
build_script:
- ps: dotnet --info
- ps: gitversion /version
- - ps: .\build.ps1 --target=ci #--verbosity=diagnostic
+ - ps: .\build.ps1 --target=ci --verbosity=diagnostic
after_build:
- ps: gci -Filter *.trx -Path .\TestResults\ | % { (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $_.FullName)) }
diff --git a/build.cake b/build.cake
index 66e70fc3b0..f1d2e87910 100644
--- a/build.cake
+++ b/build.cake
@@ -5,10 +5,9 @@
#tool dotnet:?package=NuGetKeyVaultSignTool&version=3.2.3
#tool dotnet:?package=AzureSignTool&version=4.0.1
#tool dotnet:?package=GitReleaseManager.Tool&version=0.15.0
-#tool dotnet:?package=XamlStyler.Console&version=3.2206.4
-
+#tool dotnet:?package=XamlStyler.Console&version=3.2404.2
#tool nuget:?package=GitVersion.CommandLine&version=5.12.0
-#tool nuget:?package=xunit.runner.console&version=2.5.2
+#tool nuget:?package=NUnit.ConsoleRunner&version=3.18.3
#addin nuget:?package=Cake.Figlet&version=2.0.1
diff --git a/src/Directory.Build.Props b/src/Directory.Build.Props
index c8701cf070..d77e280e79 100644
--- a/src/Directory.Build.Props
+++ b/src/Directory.Build.Props
@@ -67,8 +67,14 @@
-
-
+
+ all
+ compile; build
+
+
+ all
+ build;analyzers
+
diff --git a/src/Directory.packages.props b/src/Directory.packages.props
index 091885fb03..482875aeb2 100644
--- a/src/Directory.packages.props
+++ b/src/Directory.packages.props
@@ -4,32 +4,33 @@
true
-
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
+
+
+
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/App.xaml.cs b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/App.xaml.cs
index 211f14b3dc..01d8d50c42 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/App.xaml.cs
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/App.xaml.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Windows;
+using ControlzEx.Theming;
namespace MetroDemo
{
@@ -11,5 +12,25 @@ namespace MetroDemo
///
public partial class App : Application
{
+ ///
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ base.OnStartup(e);
+
+ ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncAll;
+
+ ThemeManager.Current.SyncTheme();
+
+ ThemeManager.Current.ThemeChanged += CurrentOnThemeChanged;
+
+#pragma warning disable CS0618 // Type or member is obsolete
+ AppModeHelper.SyncAppMode();
+
+ void CurrentOnThemeChanged(object? sender, ThemeChangedEventArgs themeChangedEventArgs)
+ {
+ AppModeHelper.SyncAppMode();
+ }
+#pragma warning restore CS0618 // Type or member is obsolete
+ }
}
}
\ No newline at end of file
diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/ButtonsExample.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/ButtonsExample.xaml
index fe92eddd82..64515a99d1 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/ButtonsExample.xaml
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/ButtonsExample.xaml
@@ -329,8 +329,8 @@
+ IsOn="{Binding CanUseToggleSwitch, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+ Toggled="ToggleSwitch_OnToggled" />
-
+
diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
index c555c141ec..2be2b1512e 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/ExampleViews/TextExamples.xaml
@@ -376,9 +376,9 @@
-
diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MainWindow.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MainWindow.xaml
index 0fccc39e6d..0e19b9cc72 100644
--- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MainWindow.xaml
+++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MainWindow.xaml
@@ -114,6 +114,14 @@
+
+
+
+
+
+
@@ -238,6 +246,18 @@
+
+
+
+
diff --git a/src/MahApps.Metro/Styles/Themes/GeneratorParameters.json b/src/MahApps.Metro/Styles/Themes/GeneratorParameters.json
index 8769954c75..fdfc8ed4ee 100644
--- a/src/MahApps.Metro/Styles/Themes/GeneratorParameters.json
+++ b/src/MahApps.Metro/Styles/Themes/GeneratorParameters.json
@@ -77,7 +77,9 @@
"MahApps.Brushes.SystemControlHighlightListAccentHigh.Opacity": "0.9",
"MahApps.Brushes.SystemControlHighlightListAccentLow.Opacity": "0.6",
"MahApps.Brushes.SystemControlHighlightListAccentMedium.Opacity": "0.8",
- "MahApps.Brushes.SystemControlTransientBorder.Opacity": "0.36"
+ "MahApps.Brushes.SystemControlTransientBorder.Opacity": "0.36",
+ "MahApps.Brushes.Window.Background.Backdrop.Acrylic": "#60000000",
+ "MahApps.Brushes.Window.Background.Backdrop.Auto": "#BB000000"
}
},
{
@@ -153,7 +155,9 @@
"MahApps.Brushes.SystemControlHighlightListAccentHigh.Opacity": "0.7",
"MahApps.Brushes.SystemControlHighlightListAccentLow.Opacity": "0.4",
"MahApps.Brushes.SystemControlHighlightListAccentMedium.Opacity": "0.6",
- "MahApps.Brushes.SystemControlTransientBorder.Opacity": "0.14"
+ "MahApps.Brushes.SystemControlTransientBorder.Opacity": "0.14",
+ "MahApps.Brushes.Window.Background.Backdrop.Acrylic": "#60FFFFFF",
+ "MahApps.Brushes.Window.Background.Backdrop.Auto": "#BBFFFFFF"
}
}
],
diff --git a/src/MahApps.Metro/Styles/Themes/Theme.Template.xaml b/src/MahApps.Metro/Styles/Themes/Theme.Template.xaml
index cce0cb79f0..23101ccc68 100644
--- a/src/MahApps.Metro/Styles/Themes/Theme.Template.xaml
+++ b/src/MahApps.Metro/Styles/Themes/Theme.Template.xaml
@@ -147,6 +147,8 @@
+
+
diff --git a/src/MahApps.Metro/Themes/DateTimePicker.xaml b/src/MahApps.Metro/Themes/DateTimePicker.xaml
index 4c6a1d26c3..56a9d8b9d0 100644
--- a/src/MahApps.Metro/Themes/DateTimePicker.xaml
+++ b/src/MahApps.Metro/Themes/DateTimePicker.xaml
@@ -356,8 +356,8 @@
ItemsSource="{TemplateBinding SourceHours}" />
+ Content=":"
+ Visibility="Collapsed" />
+ Content=":"
+ Visibility="Collapsed" />
+
@@ -592,6 +593,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/AssemblySetup.cs b/src/Mahapps.Metro.Tests/AssemblySetup.cs
new file mode 100644
index 0000000000..7bd697080e
--- /dev/null
+++ b/src/Mahapps.Metro.Tests/AssemblySetup.cs
@@ -0,0 +1,26 @@
+using System.Threading;
+using System.Windows;
+using System.Windows.Threading;
+using NUnit.Framework;
+
+namespace MahApps.Metro.Tests
+{
+ [SetUpFixture]
+ public class AssemblySetup
+ {
+ [OneTimeSetUp]
+ public void Setup()
+ {
+ SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
+
+ var app = new TestApp { ShutdownMode = ShutdownMode.OnExplicitShutdown };
+ app.InitializeComponent();
+ }
+
+ [OneTimeTearDown]
+ public void TearDown()
+ {
+ Dispatcher.CurrentDispatcher.InvokeShutdown();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/MahApps.Metro.Tests.csproj b/src/Mahapps.Metro.Tests/MahApps.Metro.Tests.csproj
index 32209c0777..5e8493a408 100644
--- a/src/Mahapps.Metro.Tests/MahApps.Metro.Tests.csproj
+++ b/src/Mahapps.Metro.Tests/MahApps.Metro.Tests.csproj
@@ -31,10 +31,12 @@
-
-
-
-
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
diff --git a/src/Mahapps.Metro.Tests/Properties/AssemblyInfo.cs b/src/Mahapps.Metro.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..9a8f7eb97d
--- /dev/null
+++ b/src/Mahapps.Metro.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1 @@
+[assembly: NUnit.Framework.Apartment(System.Threading.ApartmentState.STA)]
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestApp.xaml b/src/Mahapps.Metro.Tests/TestApp.xaml
index 41a8d58fe7..343e976fe1 100644
--- a/src/Mahapps.Metro.Tests/TestApp.xaml
+++ b/src/Mahapps.Metro.Tests/TestApp.xaml
@@ -5,7 +5,6 @@
-
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/ApplicationFixture.cs b/src/Mahapps.Metro.Tests/TestHelpers/ApplicationFixture.cs
deleted file mode 100644
index 9947243c98..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/ApplicationFixture.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Windows;
-using System.Windows.Threading;
-using Xunit;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- public class ApplicationFixture : IDisposable
- {
- public ApplicationFixture()
- {
- // ... initialize
- TestHost.Initialize();
- }
-
- public void Dispose()
- {
- // ... clean up
- GC.Collect();
- Dispatcher.ExitAllFrames();
- Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);
- }
- }
-
- [CollectionDefinition("ApplicationFixtureCollection")]
- public class ApplicationFixtureCollectionClass : ICollectionFixture
- {
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestBase.cs b/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestBase.cs
deleted file mode 100644
index d1065d475d..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestBase.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.Windows;
-using ControlzEx.Theming;
-using MahApps.Metro.Controls;
-using Xunit;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- ///
- /// This is the base class for all of our UI tests.
- ///
- [Collection("ApplicationFixtureCollection")]
- public class AutomationTestBase : IDisposable
- {
- public AutomationTestBase()
- {
- var message = $"Create test class '{this.GetType().Name}' with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
-
- // Reset the application as good as we can
- Application.Current.Invoke(() =>
- {
- var windows = Application.Current.Windows.OfType().ToList();
- foreach (Window window in windows)
- {
- window.Close();
- }
- });
-
- Application.Current.Invoke(() => { ThemeManager.Current.ChangeTheme(Application.Current, "Light.Blue"); });
- }
-
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- public virtual void Dispose()
- {
- var message = $"Dispose test class '{this.GetType().Name}' with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestFixtureBase.cs b/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestFixtureBase.cs
deleted file mode 100644
index 33002866f6..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/AutomationTestFixtureBase.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Xunit;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- public class AutomationTestFixtureBase : AutomationTestBase, IClassFixture
- where TFixture : class
- {
- protected readonly TFixture fixture;
-
- public AutomationTestFixtureBase(TFixture fixture)
- : base()
- {
- this.fixture = fixture;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/DisplayTestMethodNameAttribute.cs b/src/Mahapps.Metro.Tests/TestHelpers/DisplayTestMethodNameAttribute.cs
deleted file mode 100644
index f02bc5cf5c..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/DisplayTestMethodNameAttribute.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Reflection;
-using System.Threading;
-using System.Windows;
-using Xunit.Sdk;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- public class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute
- {
- public override void Before(MethodInfo methodUnderTest)
- {
- var message = $"Setup for test '{methodUnderTest.Name}' with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
- }
-
- public override void After(MethodInfo methodUnderTest)
- {
- var message = $"TearDown for test '{methodUnderTest.Name}' with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/SwitchContextToUiThreadAwaiter.cs b/src/Mahapps.Metro.Tests/TestHelpers/SwitchContextToUiThreadAwaiter.cs
deleted file mode 100644
index 636872b3c7..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/SwitchContextToUiThreadAwaiter.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Windows.Threading;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- public class SwitchContextToUiThreadAwaiter : INotifyCompletion
- {
- private readonly Dispatcher uiContext;
-
- public SwitchContextToUiThreadAwaiter(Dispatcher uiContext)
- {
- this.uiContext = uiContext;
- }
-
- public SwitchContextToUiThreadAwaiter GetAwaiter()
- {
- return this;
- }
-
- public bool IsCompleted => false;
-
- public void OnCompleted(Action continuation)
- {
- this.uiContext.Invoke(new Action(continuation));
- }
-
- public void GetResult()
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/TestHost.cs b/src/Mahapps.Metro.Tests/TestHelpers/TestHost.cs
deleted file mode 100644
index bde772580d..0000000000
--- a/src/Mahapps.Metro.Tests/TestHelpers/TestHost.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows;
-
-namespace MahApps.Metro.Tests.TestHelpers
-{
- ///
- /// This class is the ultimate hack to work around that we can't
- /// create more than one application in the same AppDomain
- ///
- /// It is initialized once at startup and is never properly cleaned up,
- /// this means the AppDomain will throw an exception when xUnit unloads it.
- ///
- /// Your test runner will inevitably hate you and hang endlessly after every test has run.
- /// The Resharper runner will also throw an exception message in your face.
- ///
- /// Better than no unit tests.
- ///
- public class TestHost
- {
- private TestApp? app;
- private readonly Thread? appThread;
- private readonly AutoResetEvent gate = new(false);
-
- private static TestHost? testHost;
-
- public static void Initialize()
- {
- testHost ??= new TestHost();
- }
-
- private TestHost()
- {
- this.appThread = new Thread(this.StartDispatcher);
- this.appThread.SetApartmentState(ApartmentState.STA);
- this.appThread.Start();
-
- this.gate.WaitOne();
- }
-
- private void StartDispatcher()
- {
- this.app = new TestApp { ShutdownMode = ShutdownMode.OnExplicitShutdown };
- this.app.InitializeComponent();
- this.app.Exit += (_, _) =>
- {
- var message = $"Exit TestApp with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
- };
- this.app.Startup += async (_, _) =>
- {
- var message = $"Start TestApp with Thread.CurrentThread: {Thread.CurrentThread.ManagedThreadId}" +
- $" and Current.Dispatcher.Thread: {Application.Current.Dispatcher.Thread.ManagedThreadId}";
- Debug.WriteLine(message);
- this.gate.Set();
- await Task.Yield();
- };
- this.app.Run();
- }
-
- ///
- /// Await this method in every test that should run on the UI thread.
- ///
- public static SwitchContextToUiThreadAwaiter SwitchToAppThread()
- {
- if (testHost?.app is null)
- {
- throw new InvalidOperationException($"{nameof(TestHost)} is not initialized!");
- }
-
- return new SwitchContextToUiThreadAwaiter(testHost.app.Dispatcher);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Mahapps.Metro.Tests/TestHelpers/WindowHelpers.cs b/src/Mahapps.Metro.Tests/TestHelpers/WindowHelpers.cs
index 67dc7d148a..d46c48d681 100644
--- a/src/Mahapps.Metro.Tests/TestHelpers/WindowHelpers.cs
+++ b/src/Mahapps.Metro.Tests/TestHelpers/WindowHelpers.cs
@@ -3,13 +3,14 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using MahApps.Metro.Controls;
-using Xunit;
+using NUnit.Framework;
namespace MahApps.Metro.Tests.TestHelpers
{
@@ -22,10 +23,19 @@ public static Task CreateInvisibleWindowAsync(Action? onLoadedAction =
var window = new T
{
- Visibility = Visibility.Hidden,
+ Width = 800,
+ Height = 600,
ShowInTaskbar = false
};
+ if (Debugger.IsAttached == false)
+ {
+ window.Left = int.MinValue;
+ window.Top = int.MinValue;
+ }
+
+ window.SetCurrentValue(FrameworkElement.UseLayoutRoundingProperty, true);
+
void OnLoaded(object sender, RoutedEventArgs e)
{
window.Loaded -= OnLoaded;
@@ -49,21 +59,21 @@ void OnActivated(object sender, EventArgs args)
public static void AssertWindowCommandsColor(this MetroWindow window, Color color)
{
- Assert.NotNull(window.RightWindowCommands);
+ Assert.That(window.RightWindowCommands, Is.Not.Null);
foreach (var element in window.RightWindowCommands!.Items.OfType