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 @@ + + + + + + + + <Policy Inspect="True" Prefix="PART_" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="PART_" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> <Policy><Descriptor Staticness="Instance" AccessRightKinds="Public" Description="Test methods"><ElementKinds><Kind Name="TEST_TYPE" /><Kind Name="TEST_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> @@ -796,11 +799,13 @@ See the LICENSE file in the project root for more information. True True True + True True True True True True + True True True True diff --git a/src/MahApps.Metro/Controls/Icons/PathIcon.cs b/src/MahApps.Metro/Controls/Icons/PathIcon.cs index 02e3426476..5915982f35 100644 --- a/src/MahApps.Metro/Controls/Icons/PathIcon.cs +++ b/src/MahApps.Metro/Controls/Icons/PathIcon.cs @@ -2,6 +2,7 @@ // 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.ComponentModel; using System.Windows; using System.Windows.Media; using System.Windows.Shapes; @@ -23,6 +24,7 @@ public static readonly DependencyProperty DataProperty /// /// Gets or sets a Geometry that specifies the shape to be drawn. In XAML this can also be set using the Path Markup Syntax. /// + [TypeConverter(typeof(GeometryConverter))] public Geometry? Data { get => (Geometry?)this.GetValue(DataProperty); diff --git a/src/MahApps.Metro/Controls/MultiSelectionComboBox/MultiSelectionComboBox.cs b/src/MahApps.Metro/Controls/MultiSelectionComboBox/MultiSelectionComboBox.cs index 0fe6ae079b..819f8a587f 100644 --- a/src/MahApps.Metro/Controls/MultiSelectionComboBox/MultiSelectionComboBox.cs +++ b/src/MahApps.Metro/Controls/MultiSelectionComboBox/MultiSelectionComboBox.cs @@ -43,7 +43,27 @@ static MultiSelectionComboBox() public MultiSelectionComboBox() { - this.SetValue(SelectedItemsPropertyKey, new ObservableCollection()); + var collection = new ObservableCollection(); + this.SetValue(SelectedItemsPropertyKey, collection); + } + + /// + /// Raise the SelectionChanged event. + /// + private void InvokeSelectionChanged(IList removedItems, IList addedItems) + { + var selectionChanged = new SelectionChangedEventArgs( + Selector.SelectionChangedEvent, + removedItems, + addedItems) + { + Source = this + }; + + base.OnSelectionChanged(selectionChanged); + + this.UpdateDisplaySelectedItems(); + this.UpdateEditableText(); } #endregion @@ -842,7 +862,7 @@ private void UpdateDisplaySelectedItems(SelectedItemsOrderType selectedItemsOrde private void SelectItemsFromText(int millisecondsToWait) { - if (!this.isUserdefinedTextInputPending || this.isTextChanging) + if (!this.IsEditable || !this.isUserdefinedTextInputPending || this.isTextChanging) { return; } @@ -1114,7 +1134,7 @@ private static void ExecutedClearContentCommand(object sender, ExecutedRoutedEve } } - multiSelectionCombo.ResetEditableText(true); + //multiSelectionCombo.ResetEditableText(true); } } @@ -1186,14 +1206,16 @@ public override void OnApplyTemplate() if (this.PART_PopupListBox is not null) { - this.BeginInvoke(() => - { - this.PART_PopupListBox.SelectionChanged += this.PART_PopupListBox_SelectionChanged; - - this.SyncSelectedItems(this.SelectedItems, this.PART_PopupListBox.SelectedItems, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - - this.PART_PopupListBox.SelectionChanged -= this.PART_PopupListBox_SelectionChanged; - }, DispatcherPriority.DataBind); + this.PART_PopupListBox.SelectionChanged += this.PART_PopupListBox_SelectionChanged; + this.SyncSelectedItems(this.SelectedItems, this.PART_PopupListBox.SelectedItems, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + this.PART_PopupListBox.SelectionChanged -= this.PART_PopupListBox_SelectionChanged; + + //this.BeginInvoke(() => + // { + // this.PART_PopupListBox.SelectionChanged += this.PART_PopupListBox_SelectionChanged; + // this.SyncSelectedItems(this.SelectedItems, this.PART_PopupListBox.SelectedItems, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + // this.PART_PopupListBox.SelectionChanged -= this.PART_PopupListBox_SelectionChanged; + // }, DispatcherPriority.DataBind); } // Do update the text and selection @@ -1837,6 +1859,34 @@ private void SelectedItemsImpl_CollectionChanged(object sender, NotifyCollection #endif { this.SyncSelectedItems(sender as IList, this.PART_PopupListBox?.SelectedItems, e); + + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + if (e.NewItems is not null) + { + this.InvokeSelectionChanged(new List(), e.NewItems.Cast().ToList()); + } + + break; + case NotifyCollectionChangedAction.Remove: + if (e.OldItems is not null) + { + this.InvokeSelectionChanged(e.OldItems.Cast().ToList(), new List()); + } + + break; + case NotifyCollectionChangedAction.Reset: + case NotifyCollectionChangedAction.Replace: + if (e.NewItems is not null && e.OldItems is not null) + { + this.InvokeSelectionChanged(e.OldItems.Cast().ToList(), e.NewItems.Cast().ToList()); + } + + break; + case NotifyCollectionChangedAction.Move: + break; // order within SelectedItems doesn't matter + } } private void SyncSelectedItems(IList? sourceCollection, IList? targetCollection, NotifyCollectionChangedEventArgs e) @@ -1953,6 +2003,7 @@ private void PART_SelectedItemsPresenter_MouseLeftButtonUp(object sender, MouseB { // If we have a ScrollViewer (ListBox has) we need to handle this event here as it will not be forwarded to the ToggleButton this.SetCurrentValue(IsDropDownOpenProperty, BooleanBoxes.Box(!this.IsDropDownOpen)); + e.Handled = true; } private void PART_SelectedItemsPresenter_SelectionChanged(object sender, SelectionChangedEventArgs e) diff --git a/src/MahApps.Metro/MahApps.Metro.csproj b/src/MahApps.Metro/MahApps.Metro.csproj index a7b9cd1ed7..674b762b5b 100644 --- a/src/MahApps.Metro/MahApps.Metro.csproj +++ b/src/MahApps.Metro/MahApps.Metro.csproj @@ -1,4 +1,4 @@ - + @@ -33,6 +33,12 @@ all runtime; build; native; contentfiles; analyzers + + + + + + 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}" /> - - - - + + + + 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