Browse Source

Merge pull request #7256 from AvaloniaUI/fast-theme-switching-fluent-theme

Fast Fluent theme switching
pull/7270/head
Max Katz 5 years ago
committed by GitHub
parent
commit
4cd6ff6a89
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      samples/ControlCatalog/App.xaml.cs
  2. 42
      samples/ControlCatalog/MainView.xaml.cs
  3. 96
      src/Avalonia.Themes.Fluent/FluentTheme.cs

33
samples/ControlCatalog/App.xaml.cs

@ -5,6 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling; using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Themes.Fluent;
using ControlCatalog.ViewModels; using ControlCatalog.ViewModels;
namespace ControlCatalog namespace ControlCatalog
@ -16,33 +17,17 @@ namespace ControlCatalog
DataContext = new ApplicationViewModel(); DataContext = new ApplicationViewModel();
} }
private static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles")) public static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{ {
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml") Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml")
}; };
private static readonly StyleInclude DataGridDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles")) public static readonly StyleInclude DataGridDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{ {
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Default.xaml") Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Default.xaml")
}; };
public static Styles FluentDark = new Styles public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles"));
{
new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml")
},
DataGridFluent
};
public static Styles FluentLight = new Styles
{
new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml")
},
DataGridFluent
};
public static Styles DefaultLight = new Styles public static Styles DefaultLight = new Styles
{ {
@ -65,8 +50,7 @@ namespace ControlCatalog
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{ {
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml") Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
}, }
DataGridDefault
}; };
public static Styles DefaultDark = new Styles public static Styles DefaultDark = new Styles
@ -90,14 +74,13 @@ namespace ControlCatalog
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{ {
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml") Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
}, }
DataGridDefault
}; };
public override void Initialize() public override void Initialize()
{ {
Styles.Insert(0, FluentLight); Styles.Insert(0, Fluent);
Styles.Insert(1, DataGridFluent);
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }

42
samples/ControlCatalog/MainView.xaml.cs

@ -3,14 +3,12 @@ using System.Collections;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Markup.Xaml.XamlIl;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Immutable; using Avalonia.Media.Immutable;
using Avalonia.Platform; using Avalonia.Platform;
using ControlCatalog.Pages; using Avalonia.Themes.Fluent;
using ControlCatalog.Models; using ControlCatalog.Models;
using ControlCatalog.Pages;
namespace ControlCatalog namespace ControlCatalog
{ {
@ -43,14 +41,36 @@ namespace ControlCatalog
{ {
if (themes.SelectedItem is CatalogTheme theme) if (themes.SelectedItem is CatalogTheme theme)
{ {
Application.Current.Styles[0] = theme switch var themeStyle = Application.Current.Styles[0];
if (theme == CatalogTheme.FluentLight)
{
if (App.Fluent.Mode != FluentThemeMode.Light)
{
App.Fluent.Mode = FluentThemeMode.Light;
}
Application.Current.Styles[0] = App.Fluent;
Application.Current.Styles[1] = App.DataGridFluent;
}
else if (theme == CatalogTheme.FluentDark)
{
if (App.Fluent.Mode != FluentThemeMode.Dark)
{
App.Fluent.Mode = FluentThemeMode.Dark;
}
Application.Current.Styles[0] = App.Fluent;
Application.Current.Styles[1] = App.DataGridFluent;
}
else if (theme == CatalogTheme.DefaultLight)
{
Application.Current.Styles[0] = App.DefaultLight;
Application.Current.Styles[1] = App.DataGridDefault;
}
else if (theme == CatalogTheme.DefaultDark)
{ {
CatalogTheme.FluentLight => App.FluentLight, Application.Current.Styles[0] = App.DefaultDark;
CatalogTheme.FluentDark => App.FluentDark, Application.Current.Styles[1] = App.DataGridDefault;
CatalogTheme.DefaultLight => App.DefaultLight, }
CatalogTheme.DefaultDark => App.DefaultDark,
_ => Application.Current.Styles[0]
};
} }
}; };

96
src/Avalonia.Themes.Fluent/FluentTheme.cs

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling; using Avalonia.Styling;
#nullable enable #nullable enable
@ -17,11 +18,14 @@ namespace Avalonia.Themes.Fluent
/// <summary> /// <summary>
/// Includes the fluent theme in an application. /// Includes the fluent theme in an application.
/// </summary> /// </summary>
public class FluentTheme : IStyle, IResourceProvider public class FluentTheme : AvaloniaObject, IStyle, IResourceProvider
{ {
private readonly Uri _baseUri; private readonly Uri _baseUri;
private IStyle[]? _loaded; private Styles _fluentDark = new();
private Styles _fluentLight = new();
private Styles _sharedStyles = new();
private bool _isLoading; private bool _isLoading;
private IStyle? _loaded;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="FluentTheme"/> class. /// Initializes a new instance of the <see cref="FluentTheme"/> class.
@ -30,6 +34,7 @@ namespace Avalonia.Themes.Fluent
public FluentTheme(Uri baseUri) public FluentTheme(Uri baseUri)
{ {
_baseUri = baseUri; _baseUri = baseUri;
InitStyles(baseUri);
} }
/// <summary> /// <summary>
@ -39,12 +44,37 @@ namespace Avalonia.Themes.Fluent
public FluentTheme(IServiceProvider serviceProvider) public FluentTheme(IServiceProvider serviceProvider)
{ {
_baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri; _baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri;
InitStyles(_baseUri);
} }
public static readonly StyledProperty<FluentThemeMode> ModeProperty =
AvaloniaProperty.Register<FluentTheme, FluentThemeMode>(nameof(Mode));
/// <summary> /// <summary>
/// Gets or sets the mode of the fluent theme (light, dark). /// Gets or sets the mode of the fluent theme (light, dark).
/// </summary> /// </summary>
public FluentThemeMode Mode { get; set; } public FluentThemeMode Mode
{
get => GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == ModeProperty)
{
if (Mode == FluentThemeMode.Dark)
{
(Loaded as Styles)![1] = _fluentDark[0];
(Loaded as Styles)![2] = _fluentDark[1];
}
else
{
(Loaded as Styles)![1] = _fluentLight[0];
(Loaded as Styles)![2] = _fluentLight[1];
}
}
}
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner; public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
@ -58,18 +88,25 @@ namespace Avalonia.Themes.Fluent
if (_loaded == null) if (_loaded == null)
{ {
_isLoading = true; _isLoading = true;
var loaded = (IStyle)AvaloniaXamlLoader.Load(GetUri(), _baseUri);
_loaded = new[] { loaded }; if (Mode == FluentThemeMode.Light)
{
_loaded = new Styles() { _sharedStyles , _fluentLight[0], _fluentLight[1] };
}
else if (Mode == FluentThemeMode.Dark)
{
_loaded = new Styles() { _sharedStyles, _fluentDark[0], _fluentDark[1] };
}
_isLoading = false; _isLoading = false;
} }
return _loaded?[0]!; return _loaded!;
} }
} }
bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false; bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false;
IReadOnlyList<IStyle> IStyle.Children => _loaded ?? Array.Empty<IStyle>(); IReadOnlyList<IStyle> IStyle.Children => _loaded?.Children ?? Array.Empty<IStyle>();
public event EventHandler OwnerChanged public event EventHandler OwnerChanged
{ {
@ -105,10 +142,47 @@ namespace Avalonia.Themes.Fluent
void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner); void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner);
void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner); void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner);
private Uri GetUri() => Mode switch private void InitStyles(Uri baseUri)
{ {
FluentThemeMode.Dark => new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml", UriKind.Absolute), _sharedStyles = new Styles
_ => new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml", UriKind.Absolute), {
}; new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Controls/FluentControls.xaml")
}
};
_fluentLight = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml")
}
};
_fluentDark = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml")
}
};
}
} }
} }

Loading…
Cancel
Save