This commit is contained in:
wieslawsoltes 2019-04-05 12:19:41 +02:00
Родитель e61ca81ddf
Коммит 1fc0f0f465
6 изменённых файлов: 53 добавлений и 35 удалений

Просмотреть файл

@ -16,9 +16,9 @@ Theme manager for [Avalonia](https://github.com/AvaloniaUI/Avalonia) application
Theme manager searches user provided themes directory for `*.xaml` theme files otherwise built-in `Light` and `Dark` theme are used.
The `ThemeSelector` static `Instance` property neeeds to be initalized before using `ThemeSelector` class.
The `ThemeSelector` is created and initalized by calling static `Create` method.
The `ThemeSelector` uses `Styles[0]` property of `Windows` to insert selected theme `Style`.
The `ThemeSelector` uses `Styles[0]` property of `Window` to insert selected theme `Style`.
`App.xaml`
```XAML
@ -44,6 +44,8 @@ namespace AvaloniaApp
{
public class App : Application
{
public static IThemeSelector Selector;
[STAThread]
static void Main(string[] args)
{
@ -52,12 +54,12 @@ namespace AvaloniaApp
static void AppMain(Application app, string[] args)
{
ThemeSelector.Instance = new ThemeSelector("Themes");
ThemeSelector.Instance.LoadSelectedTheme("AvaloniaApp.theme");
Selector = ThemeSelector.Create("Themes");
Selector.LoadSelectedTheme("AvaloniaApp.theme");
app.Run(new MainWindow());
ThemeSelector.Instance.SaveSelectedTheme("AvaloniaApp.theme");
Selector.SaveSelectedTheme("AvaloniaApp.theme");
}
public static AppBuilder BuildAvaloniaApp()
@ -79,16 +81,17 @@ namespace AvaloniaApp
<Window x:Class="AvaloniaApp.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Avalonia.ThemeManager;assembly=Avalonia.ThemeManager"
xmlns:app="clr-namespace:AvaloniaApp;assembly=AvaloniaApp"
xmlns:manager="clr-namespace:Avalonia.ThemeManager;assembly=Avalonia.ThemeManager"
Title="AvaloniaApp" Width="800" Height="600"
Foreground="{DynamicResource ThemeForegroundBrush}">
<Window.Resources>
<Themes:ObjectEqualityMultiConverter x:Key="ObjectEqualityMultiConverter"/>
<manager:ObjectEqualityMultiConverter x:Key="ObjectEqualityMultiConverter"/>
</Window.Resources>
<Grid RowDefinitions="Auto,*">
<Menu Grid.Row="0">
<MenuItem Header="_View">
<MenuItem Header="_Theme" DataContext="{x:Static Themes:ThemeSelector.Instance}" Items="{Binding Themes}">
<MenuItem Header="_Theme" DataContext="{x:Static app:App.Selector}" Items="{Binding Themes}">
<MenuItem.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Name}"/>
@ -130,7 +133,7 @@ namespace AvaloniaApp
{
this.InitializeComponent();
this.AttachDevTools();
ThemeSelector.Instance.EnableThemes(this);
App.Selector.EnableThemes(this);
}
private void InitializeComponent()
@ -141,7 +144,7 @@ namespace AvaloniaApp
}
```
The `ThemeSelector.Instance.EnableThemes(this);` can be used in multiple windows.
The `EnableThemes(...);` can be used to enable themes for multiple windows.
## License

Просмотреть файл

@ -8,6 +8,8 @@ namespace AvaloniaApp
{
public class App : Application
{
public static IThemeSelector Selector;
[STAThread]
static void Main(string[] args)
{
@ -16,12 +18,12 @@ namespace AvaloniaApp
static void AppMain(Application app, string[] args)
{
ThemeSelector.Instance = new ThemeSelector("Themes");
ThemeSelector.Instance.LoadSelectedTheme("AvaloniaApp.theme");
Selector = ThemeSelector.Create("Themes");
Selector.LoadSelectedTheme("AvaloniaApp.theme");
app.Run(new MainWindow());
ThemeSelector.Instance.SaveSelectedTheme("AvaloniaApp.theme");
Selector.SaveSelectedTheme("AvaloniaApp.theme");
}
public static AppBuilder BuildAvaloniaApp()

Просмотреть файл

@ -1,16 +1,17 @@
<Window x:Class="AvaloniaApp.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Avalonia.ThemeManager;assembly=Avalonia.ThemeManager"
xmlns:app="clr-namespace:AvaloniaApp;assembly=AvaloniaApp"
xmlns:manager="clr-namespace:Avalonia.ThemeManager;assembly=Avalonia.ThemeManager"
Title="AvaloniaApp" Width="800" Height="600"
Foreground="{DynamicResource ThemeForegroundBrush}">
<Window.Resources>
<Themes:ObjectEqualityMultiConverter x:Key="ObjectEqualityMultiConverter"/>
<manager:ObjectEqualityMultiConverter x:Key="ObjectEqualityMultiConverter"/>
</Window.Resources>
<Grid RowDefinitions="Auto,*">
<Menu Grid.Row="0">
<MenuItem Header="_View">
<MenuItem Header="_Theme" DataContext="{x:Static Themes:ThemeSelector.Instance}" Items="{Binding Themes}">
<MenuItem Header="_Theme" DataContext="{x:Static app:App.Selector}" Items="{Binding Themes}">
<MenuItem.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Name}"/>

Просмотреть файл

@ -11,7 +11,7 @@ namespace AvaloniaApp
{
this.InitializeComponent();
this.AttachDevTools();
ThemeSelector.Instance.EnableThemes(this);
App.Selector.EnableThemes(this);
}
private void InitializeComponent()

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.ObjectModel;
@ -13,11 +13,11 @@ using ReactiveUI;
namespace Avalonia.ThemeManager
{
public class Theme : ReactiveObject
public class Theme : ReactiveObject, ITheme
{
private string _name;
private IStyle _style;
private ThemeSelector _selector;
private IThemeSelector _selector;
public string Name
{
@ -31,7 +31,7 @@ namespace Avalonia.ThemeManager
set => this.RaiseAndSetIfChanged(ref _style, value);
}
public ThemeSelector Selector
public IThemeSelector Selector
{
get => _selector;
set => this.RaiseAndSetIfChanged(ref _selector, value);

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
@ -13,37 +14,48 @@ using ReactiveUI;
namespace Avalonia.ThemeManager
{
public class ThemeSelector : ReactiveObject
public sealed class ThemeSelector : ReactiveObject, IThemeSelector
{
public static ThemeSelector Instance;
private Theme _selectedTheme;
private ObservableCollection<Theme> _themes;
private ObservableCollection<Window> _windows;
private ITheme _selectedTheme;
private IList<ITheme> _themes;
private IList<Window> _windows;
public Theme SelectedTheme
public ITheme SelectedTheme
{
get => _selectedTheme;
set => this.RaiseAndSetIfChanged(ref _selectedTheme, value);
}
public ObservableCollection<Theme> Themes
public IList<ITheme> Themes
{
get => _themes;
set => this.RaiseAndSetIfChanged(ref _themes, value);
}
public ObservableCollection<Window> Windows
public IList<Window> Windows
{
get => _windows;
set => this.RaiseAndSetIfChanged(ref _windows, value);
}
public ThemeSelector(string path)
private ThemeSelector()
{
_themes = new ObservableCollection<Theme>();
}
try
public static IThemeSelector Create(string path)
{
return new ThemeSelector()
{
Themes = new ObservableCollection<ITheme>(),
Windows = new ObservableCollection<Window>()
}.LoadThemes(path);
}
private IThemeSelector LoadThemes(string path)
{
try
{
foreach (string file in System.IO.Directory.EnumerateFiles(path, "*.xaml"))
{
@ -64,10 +76,10 @@ namespace Avalonia.ThemeManager
_selectedTheme = _themes.FirstOrDefault();
_windows = new ObservableCollection<Window>();
return this;
}
public Theme LoadTheme(string file)
public ITheme LoadTheme(string file)
{
var name = System.IO.Path.GetFileNameWithoutExtension(file);
var xaml = System.IO.File.ReadAllText(file);
@ -97,7 +109,7 @@ namespace Avalonia.ThemeManager
};
}
public void ApplyTheme(Theme theme)
public void ApplyTheme(ITheme theme)
{
if (theme != null)
{