diff --git a/Screenbox/Pages/MainPage.xaml b/Screenbox/Pages/MainPage.xaml index 5e45cec83..2d8f88e31 100644 --- a/Screenbox/Pages/MainPage.xaml +++ b/Screenbox/Pages/MainPage.xaml @@ -15,6 +15,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:strings="using:Screenbox.Strings" + xmlns:triggers="using:Screenbox.Triggers" muxc:BackdropMaterial.ApplyToRootOrPageBackground="True" Loaded="MainPage_Loaded" mc:Ignorable="d"> @@ -412,9 +413,10 @@ - - + + + diff --git a/Screenbox/Pages/MainPage.xaml.cs b/Screenbox/Pages/MainPage.xaml.cs index a8dbae963..154d9886a 100644 --- a/Screenbox/Pages/MainPage.xaml.cs +++ b/Screenbox/Pages/MainPage.xaml.cs @@ -51,9 +51,6 @@ public MainPage() // For example, when the app moves to a screen with a different DPI. coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged; - // Register a handler for when the window changes focus - Window.Current.CoreWindow.Activated += CoreWindow_Activated; - NotificationView.Translation = new Vector3(0, 0, 16); _pages = new Dictionary @@ -81,21 +78,6 @@ private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sende RightPaddingColumn.Width = new GridLength(Math.Max(sender.SystemOverlayLeftInset, sender.SystemOverlayRightInset)); } - /// - /// Change the depending on whether the app is active or inactive. - /// - private void CoreWindow_Activated(CoreWindow sender, WindowActivatedEventArgs args) - { - if (args.WindowActivationState == CoreWindowActivationState.Deactivated) - { - VisualStateManager.GoToState(this, "Deactivated", true); - } - else - { - VisualStateManager.GoToState(this, "Activated", true); - } - } - protected override void OnNavigatedTo(NavigationEventArgs e) { PlayerFrame.Navigate(typeof(PlayerPage), e.Parameter); diff --git a/Screenbox/Screenbox.csproj b/Screenbox/Screenbox.csproj index 164a38e04..3d893e075 100644 --- a/Screenbox/Screenbox.csproj +++ b/Screenbox/Screenbox.csproj @@ -309,6 +309,7 @@ + diff --git a/Screenbox/Triggers/WindowActivationModeTrigger.cs b/Screenbox/Triggers/WindowActivationModeTrigger.cs new file mode 100644 index 000000000..d7daa1ea4 --- /dev/null +++ b/Screenbox/Triggers/WindowActivationModeTrigger.cs @@ -0,0 +1,101 @@ +#nullable enable + +using Windows.UI.Core; +using Windows.UI.Xaml; + +namespace Screenbox.Triggers; + +/// +/// Represents a declarative rule that applies visual states based on the property. +/// +/// +/// Use WindowActivationModeTriggers to create rules that automatically triggers a VisualState change when +/// the window is a specified activation state. When you use WindowActivationModeTriggers in your XAML markup, +/// you don't need to handle the event and call in your code. +/// +/// +/// This example shows how to use the property with an +/// to create a declarative rule in XAML markup based on the activation state of the window. +/// +/// <Grid> +/// <StackPanel> +/// <TextBlock x:Name="FirstText" +/// Foreground="{ThemeResource TextFillColorPrimaryBrush}" +/// Text="This is a block of text. It is the 1st text block." /> +/// <TextBlock x:Name="LastText" +/// Foreground="{ThemeResource TextFillColorPrimaryBrush}" +/// Text="This is a block of text. It is the 2nd text block." /> +/// </StackPanel> +/// <VisualStateManager.VisualStateGroups> +/// <VisualStateGroup> +/// <VisualState> +/// <VisualState.StateTriggers> +/// <!-- VisualState to be triggered when the activation state of the window is Deactivated. --> +/// <local:WindowActivationModeTrigger ActivationMode="Deactivated" /> +/// </VisualState.StateTriggers> +/// +/// <VisualState.Setters> +/// <Setter Target="FirstText.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" /> +/// <Setter Target="LastText.Opacity" Value="0.4" /> +/// </VisualState.Setters> +/// </VisualState> +/// </VisualStateGroup> +/// </VisualStateManager.VisualStateGroups> +/// </Grid> +/// +/// +[Windows.Foundation.Metadata.ContractVersion(typeof(Windows.Foundation.UniversalApiContract), 327680u)] +public sealed class WindowActivationModeTrigger : StateTriggerBase +{ + private CoreWindow? _coreWindow; + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ActivationModeProperty = DependencyProperty.Register( + nameof(ActivationMode), typeof(CoreWindowActivationMode), typeof(WindowActivationModeTrigger), new PropertyMetadata(CoreWindowActivationMode.None, OnActivationModePropertyChanged)); + + /// + /// Gets or sets the activation mode that indicates whether the trigger should be applied. + /// + public CoreWindowActivationMode ActivationMode + { + get { return (CoreWindowActivationMode)GetValue(ActivationModeProperty); } + set { SetValue(ActivationModeProperty, value); } + } + + private static void OnActivationModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is WindowActivationModeTrigger trigger) + { + trigger.UpdateActivatedEventHandler(); + trigger.UpdateTrigger(); + } + } + + private void UpdateActivatedEventHandler() + { + _coreWindow = Window.Current?.CoreWindow; + + var coreWindow = _coreWindow; + if (coreWindow != null) + { + coreWindow.Activated -= OnActivated; + + if (ActivationMode is not CoreWindowActivationMode.None) + { + coreWindow.Activated += OnActivated; + } + } + } + + private void OnActivated(CoreWindow sender, WindowActivatedEventArgs args) + { + UpdateTrigger(); + } + + private void UpdateTrigger() + { + SetActive(_coreWindow?.ActivationMode == ActivationMode); + } +}