Removed Reactive stuff and do code cleanup

This commit is contained in:
Holger Börchers 2023-04-02 22:44:52 +02:00
parent 2af0df14c9
commit c2e7cc1a3c
16 changed files with 337 additions and 248 deletions

View File

@ -1,17 +1,22 @@
<Application xmlns="https://github.com/avaloniaui" <Application
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="AvaloniaCoreRTDemo.App"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" xmlns="https://github.com/avaloniaui"
RequestedThemeVariant="Light" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaCoreRTDemo.App" xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels1:ApplicationModelBase"> x:DataType="viewModels1:ApplicationModelBase"
<NativeMenu.Menu> RequestedThemeVariant="Light">
<NativeMenu> <NativeMenu.Menu>
<NativeMenuItem Header="About" Gesture="cmd+b" IsEnabled="{Binding AboutEnabled}" Command="{Binding HelpAboutMethod}"/> <NativeMenu>
</NativeMenu> <NativeMenuItem
</NativeMenu.Menu> Command="{Binding HelpAboutCommand}"
<Application.Resources> Gesture="cmd+b"
<StyleInclude x:Key="fluentDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" /> Header="About"
<StyleInclude x:Key="simpleDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml" /> IsEnabled="{Binding AboutEnabled}" />
</Application.Resources> </NativeMenu>
</NativeMenu.Menu>
<Application.Resources>
<StyleInclude x:Key="fluentDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
<StyleInclude x:Key="simpleDataGrid" Source="avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml" />
</Application.Resources>
</Application> </Application>

View File

@ -25,81 +25,81 @@ namespace AvaloniaCoreRTDemo
public override void Initialize() public override void Initialize()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
this.Name = "AvaloniaCoreRTDemo"; Name = "AvaloniaCoreRTDemo";
} }
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
this.InitializeThemes(); InitializeThemes();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
desktop.MainWindow = new MainWindow(); desktop.MainWindow = new MainWindow();
this.DataContext = desktop.MainWindow.DataContext; DataContext = desktop.MainWindow.DataContext;
} }
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
private void InitializeThemes() private void InitializeThemes()
{ {
this._simpleTheme = new SimpleTheme(); _simpleTheme = new SimpleTheme();
this._fluentTheme = new FluentTheme(); _fluentTheme = new FluentTheme();
this._fluentDataGrid = (IStyle)this.Resources["fluentDataGrid"]!; _fluentDataGrid = (IStyle)Resources["fluentDataGrid"]!;
this._simpleDataGrid = (IStyle)this.Resources["simpleDataGrid"]!; _simpleDataGrid = (IStyle)Resources["simpleDataGrid"]!;
Styles.Add(_fluentTheme); Styles.Add(_fluentTheme);
Styles.Add(_fluentDataGrid); Styles.Add(_fluentDataGrid);
this._currentTheme = ApplicationTheme.FluentLight; _currentTheme = ApplicationTheme.FluentLight;
} }
ApplicationTheme IThemeSwitch.Current => this._currentTheme; ApplicationTheme IThemeSwitch.Current => _currentTheme;
void IThemeSwitch.ChangeTheme(ApplicationTheme theme) void IThemeSwitch.ChangeTheme(ApplicationTheme theme)
{ {
if (theme == this._currentTheme) if (theme == _currentTheme)
return; return;
Boolean themeChanged = theme switch bool themeChanged = theme switch
{ {
ApplicationTheme.SimpleLight => this._currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight, ApplicationTheme.SimpleLight => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.SimpleDark => this._currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight, ApplicationTheme.SimpleDark => _currentTheme is ApplicationTheme.FluentDark or ApplicationTheme.FluentLight,
ApplicationTheme.FluentLight => this._currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark, ApplicationTheme.FluentLight => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
ApplicationTheme.FluentDark => this._currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark, ApplicationTheme.FluentDark => _currentTheme is ApplicationTheme.SimpleLight or ApplicationTheme.SimpleDark,
_ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null) _ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null)
}; };
this._currentTheme = theme; _currentTheme = theme;
switch (theme) switch (theme)
{ {
case ApplicationTheme.SimpleLight: case ApplicationTheme.SimpleLight:
this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light); SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
this.Styles[0] = this._simpleTheme; Styles[0] = _simpleTheme;
this.Styles[1] = this._simpleDataGrid; Styles[1] = _simpleDataGrid;
break; break;
case ApplicationTheme.SimpleDark: case ApplicationTheme.SimpleDark:
this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark); SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
this.Styles[0] = this._simpleTheme; Styles[0] = _simpleTheme;
this.Styles[1] = this._simpleDataGrid; Styles[1] = _simpleDataGrid;
break; break;
case ApplicationTheme.FluentLight: case ApplicationTheme.FluentLight:
this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light); SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Light);
this.Styles[0] = this._fluentTheme; Styles[0] = _fluentTheme;
this.Styles[1] = this._fluentDataGrid; Styles[1] = _fluentDataGrid;
break; break;
case ApplicationTheme.FluentDark: case ApplicationTheme.FluentDark:
this.SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark); SetValue(ThemeVariantScope.ActualThemeVariantProperty, ThemeVariant.Dark);
this.Styles[0] = this._fluentTheme; Styles[0] = _fluentTheme;
this.Styles[1] = this._fluentDataGrid; Styles[1] = _fluentDataGrid;
break; break;
} }
if (themeChanged && this.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (themeChanged && ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
MainWindow oldWindow = (desktop.MainWindow as MainWindow)!; MainWindow oldWindow = (desktop.MainWindow as MainWindow)!;
MainWindow newWindow = new MainWindow(oldWindow); MainWindow newWindow = new MainWindow(oldWindow);
desktop.MainWindow = newWindow; desktop.MainWindow = newWindow;
this.DataContext = newWindow.DataContext; DataContext = newWindow.DataContext;
oldWindow.Hide(); oldWindow.Hide();
newWindow.Show(); newWindow.Show();

View File

@ -2,7 +2,7 @@
namespace AvaloniaCoreRTDemo namespace AvaloniaCoreRTDemo
{ {
public enum ApplicationTheme : Byte public enum ApplicationTheme : byte
{ {
SimpleLight = 0, SimpleLight = 0,
SimpleDark = 1, SimpleDark = 1,

View File

@ -11,6 +11,7 @@
<PublishAot>true</PublishAot> <PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed> <PublishTrimmed>true</PublishTrimmed>
<SelfContained>true</SelfContained> <SelfContained>true</SelfContained>
<ImplicitUsing>enable</ImplicitUsing>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -50,13 +51,16 @@
<PackageReference Include="Avalonia" Version="11.0.0-*" /> <PackageReference Include="Avalonia" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-*" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Themes.Simple" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-*" /> <PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-*" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-*" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-*" />
<!--Condition below is needed to generate macOS App only.--> <!--Condition below is needed to generate macOS App only.-->
<PackageReference Include="Dotnet.Bundle" Version="0.9.13" Condition="$(RuntimeIdentifier.StartsWith('osx'))" /> <PackageReference Include="Dotnet.Bundle" Version="0.9.13" Condition="$(RuntimeIdentifier.StartsWith('osx'))" />
<PackageReference Include="MvvmGen.PureCodeGeneration" Version="1.2.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<!-- Information for Dotnet.Bundle to Generate macOS app--> <!-- Information for Dotnet.Bundle to Generate macOS app-->

View File

@ -1,12 +1,44 @@
<UserControl xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" <UserControl
xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels" x:Class="AvaloniaCoreRTDemo.Controls.MainControl"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Controls.MainControl" xmlns="https://github.com/avaloniaui"
x:CompileBindings="True" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:DataType="viewModels:MainControlViewModel"> xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*" Margin="32"> xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" TextAlignment="Center" Margin="0,6">Welcome to Avalonia UI + NativeAOT!</TextBlock> xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels"
<Image Grid.Row="1" Grid.Column="0" Stretch="None" Source="{Binding DotNetImage}"/> d:DesignHeight="450"
<Image Grid.Row="1" Grid.Column="1" Stretch="None" Source="{Binding AvaloniaImage}"/> d:DesignWidth="800"
<TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Watermark="Type here" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Text}"/> x:CompileBindings="True"
</Grid> x:DataType="viewModels:MainControlViewModel"
mc:Ignorable="d">
<Grid
Margin="32"
ColumnDefinitions="*,*"
RowDefinitions="Auto,Auto,*">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,6"
TextAlignment="Center">
Welcome to Avalonia UI + NativeAOT!
</TextBlock>
<Image
Grid.Row="1"
Grid.Column="0"
Source="{Binding DotNetImage}"
Stretch="None" />
<Image
Grid.Row="1"
Grid.Column="1"
Source="{Binding AvaloniaImage}"
Stretch="None" />
<TextBox
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
AcceptsReturn="True"
Text="{Binding Text}"
TextWrapping="Wrap"
Watermark="Type here" />
</Grid>
</UserControl> </UserControl>

View File

@ -9,18 +9,18 @@ namespace AvaloniaCoreRTDemo.Controls
{ {
public MainControl() public MainControl()
{ {
this.InitializeComponent(); InitializeComponent();
} }
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
this.DataContext = new MainControlViewModel(); DataContext = new MainControlViewModel();
} }
public void Reload(IMainWindowState model) public void Reload(IMainWindowState model)
{ {
this.DataContext = new MainControlViewModel(model); DataContext = new MainControlViewModel(model);
} }
} }
} }

View File

@ -1,48 +1,46 @@
using System; using Avalonia.Media.Imaging;
using MvvmGen;
using Avalonia.Media.Imaging;
using ReactiveUI;
namespace AvaloniaCoreRTDemo.Controls.ViewModels namespace AvaloniaCoreRTDemo.Controls.ViewModels
{ {
internal sealed class MainControlViewModel : ReactiveObject, IMainWindowState [ViewModel]
internal sealed partial class MainControlViewModel : IMainWindowState
{ {
private readonly IBitmap _dotNetImage; private IBitmap _dotNetImage;
private readonly IBitmap _avaloniaImage; private IBitmap _avaloniaImage;
private Boolean _unloadable = false; private bool _unloadable = false;
public IBitmap DotNetImage => this._dotNetImage; public IBitmap DotNetImage => _dotNetImage;
public IBitmap AvaloniaImage => this._avaloniaImage; public IBitmap AvaloniaImage => _avaloniaImage;
public String? Text { get; set; } public string? Text { get; set; }
public MainControlViewModel() partial void OnInitialize()
{ {
this._dotNetImage = Utilities.GetImageFromFile("dotnet.png"); _dotNetImage = Utilities.GetImageFromFile("dotnet.png");
this._avaloniaImage = Utilities.GetImageFromFile("avalonia.png"); _avaloniaImage = Utilities.GetImageFromFile("avalonia.png");
} }
public MainControlViewModel(IMainWindowState state) public MainControlViewModel(IMainWindowState state) : this()
{ {
this._avaloniaImage = state.AvaloniaImage; _avaloniaImage = state.AvaloniaImage;
this._dotNetImage = state.DotNetImage; _dotNetImage = state.DotNetImage;
this.Text = state.Text; Text = state.Text;
state.SetUnloadable(); state.SetUnloadable();
} }
~MainControlViewModel() ~MainControlViewModel()
{ {
if (!this._unloadable) if (!_unloadable)
{ {
this._dotNetImage.Dispose(); _dotNetImage.Dispose();
this._avaloniaImage.Dispose(); _avaloniaImage.Dispose();
} }
} }
void IMainWindowState.SetUnloadable() void IMainWindowState.SetUnloadable()
{ {
this._unloadable = true; _unloadable = true;
} }
} }
} }

View File

@ -8,9 +8,8 @@ namespace AvaloniaCoreRTDemo
{ {
IBitmap DotNetImage { get; } IBitmap DotNetImage { get; }
IBitmap AvaloniaImage { get; } IBitmap AvaloniaImage { get; }
String? Text { get; } string? Text { get; }
void SetUnloadable(); void SetUnloadable();
} }
} }

View File

@ -11,10 +11,10 @@ namespace AvaloniaCoreRTDemo
{ {
internal static class Utilities internal static class Utilities
{ {
public static readonly Boolean IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static readonly Boolean IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); public static readonly bool IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static Bitmap GetImageFromResources(String fileName) public static Bitmap GetImageFromResources(string fileName)
{ {
var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>(); var assetLoader = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}")); using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}"));
@ -27,12 +27,12 @@ namespace AvaloniaCoreRTDemo
return window.Position; return window.Position;
else else
{ {
Int32 yOffset = (Int32)(window.FrameSize.Value.Height - window.ClientSize.Height); int yOffset = (int)(window.FrameSize.Value.Height - window.ClientSize.Height);
return new(window.Position.X, window.Position.Y + yOffset); return new(window.Position.X, window.Position.Y + yOffset);
} }
} }
public static Bitmap GetImageFromFile(String path) public static Bitmap GetImageFromFile(string path)
{ {
try try
{ {
@ -44,7 +44,6 @@ namespace AvaloniaCoreRTDemo
} }
} }
private static String GetImageFullPath(String fileName) private static string GetImageFullPath(string fileName) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
=> Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
} }
} }

View File

@ -1,20 +1,50 @@
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" <Window
xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" x:Class="AvaloniaCoreRTDemo.Windows.AboutWindow"
mc:Ignorable="d" x:Class="AvaloniaCoreRTDemo.Windows.AboutWindow" d:DesignWidth="640" d:DesignHeight="256" xmlns="https://github.com/avaloniaui"
WindowState="Normal" WindowStartupLocation="CenterOwner" Height="256" MaxWidth="840" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="Width" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Title="About" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
CanResize="false" ShowInTaskbar="False" Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico" xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
x:CompileBindings="True" Title="About"
x:DataType="viewModels:AboutViewModel"> Height="256"
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ColumnDefinitions="Auto,*"> MaxWidth="840"
<Image Margin="0, 60" Grid.Column="0" Stretch="None" Source="{Binding ComputerImage}" VerticalAlignment="Top" HorizontalAlignment="Left"> d:DesignHeight="256"
</Image> d:DesignWidth="640"
<DataGrid Grid.Column="1" Items="{Binding SystemDetails}" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" HeadersVisibility="None"> x:CompileBindings="True"
<DataGrid.Columns> x:DataType="viewModels:AboutViewModel"
<DataGridTextColumn Header="Key" Binding="{Binding Key, x:DataType=viewModels:SystemDetail}" FontWeight="Bold" /> CanResize="false"
<DataGridTextColumn Header="Value" Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" /> Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico"
</DataGrid.Columns> ShowInTaskbar="False"
</DataGrid> SizeToContent="Width"
</Grid> WindowStartupLocation="CenterOwner"
WindowState="Normal"
mc:Ignorable="d">
<Grid
HorizontalAlignment="Left"
VerticalAlignment="Top"
ColumnDefinitions="Auto,*">
<Image
Grid.Column="0"
Margin="0,60"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Source="{Binding ComputerImage}"
Stretch="None" />
<DataGrid
Grid.Column="1"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
HeadersVisibility="None"
IsReadOnly="True"
Items="{Binding SystemDetails}">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Key, x:DataType=viewModels:SystemDetail}"
FontWeight="Bold"
Header="Key" />
<DataGridTextColumn Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" Header="Value" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window> </Window>

View File

@ -10,14 +10,14 @@ namespace AvaloniaCoreRTDemo.Windows
{ {
public sealed partial class AboutWindow : Window public sealed partial class AboutWindow : Window
{ {
private readonly Boolean _darkTheme; private readonly bool _darkTheme;
public AboutWindow() : this(false) { } public AboutWindow() : this(false) { }
public AboutWindow(Boolean darkTheme) public AboutWindow(bool darkTheme)
{ {
this._darkTheme = darkTheme; _darkTheme = darkTheme;
this.InitializeComponent(); InitializeComponent();
#if DEBUG #if DEBUG
this.AttachDevTools(); this.AttachDevTools();
#endif #endif
@ -26,7 +26,7 @@ namespace AvaloniaCoreRTDemo.Windows
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
this.DataContext = new AboutViewModel(this._darkTheme); DataContext = new AboutViewModel(_darkTheme);
} }
} }
} }

View File

@ -1,31 +1,63 @@
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" <Window
xmlns:controls="clr-namespace:AvaloniaCoreRTDemo.Controls" x:Class="AvaloniaCoreRTDemo.Windows.MainWindow"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" xmlns="https://github.com/avaloniaui"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Windows.MainWindow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640" Height="480" WindowStartupLocation="CenterScreen" Title="AvaloniaCoreRTDemo" Icon="avares://AvaloniaCoreRTDemo/Assets/app.ico" MinWidth="400" MinHeight="350" xmlns:controls="clr-namespace:AvaloniaCoreRTDemo.Controls"
x:CompileBindings="True" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:DataType="viewModels1:ApplicationModelBase"> xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
Title="AvaloniaCoreRTDemo"
Width="640"
Height="480"
MinWidth="400"
MinHeight="350"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="viewModels1:ApplicationModelBase"
Icon="avares://AvaloniaCoreRTDemo/Assets/app.ico"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel> <DockPanel>
<NativeMenuBar DockPanel.Dock="Top" /> <NativeMenuBar DockPanel.Dock="Top" />
<controls:MainControl Name="MainControl"/> <controls:MainControl Name="MainControl" />
</DockPanel> </DockPanel>
<NativeMenu.Menu> <NativeMenu.Menu>
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="File"> <NativeMenuItem Header="File">
<NativeMenuItem.Menu> <NativeMenuItem.Menu>
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="Exit" Gesture="cmd+e" Command="{Binding FileExitCommand}"/> <NativeMenuItem
<NativeMenuItem Header="About" Gesture="cmd+b" IsEnabled="{Binding AboutEnabled}" Command="{Binding HelpAboutMethod}"/> Command="{Binding FileExitCommand}"
Gesture="cmd+e"
Header="Exit" />
<NativeMenuItem
Command="{Binding HelpAboutCommand}"
Gesture="cmd+b"
Header="About"
IsEnabled="{Binding AboutEnabled}" />
</NativeMenu> </NativeMenu>
</NativeMenuItem.Menu> </NativeMenuItem.Menu>
</NativeMenuItem> </NativeMenuItem>
<NativeMenuItem Header="Theme"> <NativeMenuItem Header="Theme">
<NativeMenuItem.Menu> <NativeMenuItem.Menu>
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="Default Light" IsEnabled="{Binding DefaultLightEnabled}" Command="{Binding DefaultLightMethod}"/> <NativeMenuItem
<NativeMenuItem Header="Default Dark" IsEnabled="{Binding DefaultDarkEnabled}" Command="{Binding DefaultDarkMethod}"/> Command="{Binding DefaultLightCommand}"
<NativeMenuItem Header="Fluent Light" IsEnabled="{Binding FluentLightEnabled}" Command="{Binding FluentLightMethod}"/> Header="Default Light"
<NativeMenuItem Header="Fluent Dark" IsEnabled="{Binding FluentDarkEnabled}" Command="{Binding FluentDarkMethod}"/> IsEnabled="{Binding DefaultLightEnabled}" />
<NativeMenuItem
Command="{Binding DefaultDarkCommand}"
Header="Default Dark"
IsEnabled="{Binding DefaultDarkEnabled}" />
<NativeMenuItem
Command="{Binding FluentLightCommand}"
Header="Fluent Light"
IsEnabled="{Binding FluentLightEnabled}" />
<NativeMenuItem
Command="{Binding FluentDarkCommand}"
Header="Fluent Dark"
IsEnabled="{Binding FluentDarkEnabled}" />
</NativeMenu> </NativeMenu>
</NativeMenuItem.Menu> </NativeMenuItem.Menu>
</NativeMenuItem> </NativeMenuItem>

View File

@ -10,38 +10,39 @@ namespace AvaloniaCoreRTDemo.Windows
{ {
public sealed partial class MainWindow : Window, IMainWindow public sealed partial class MainWindow : Window, IMainWindow
{ {
private readonly Application? _app = App.Current; private readonly Application? _app = Application.Current;
private MainControl MainControl => this.GetControl<MainControl>("MainControl"); private MainControl MainController => this.GetControl<MainControl>("MainControl");
public MainWindow() : this(default) { } public MainWindow() : this(default) { }
public MainWindow(IMainWindow? window) public MainWindow(IMainWindow? window)
{ {
this.InitializeComponent(window); InitializeComponent(window);
#if DEBUG #if DEBUG
this.AttachDevTools(); this.AttachDevTools();
#endif #endif
} }
IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)this._app!; IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)_app!;
IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainControl.DataContext!; IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainController.DataContext!;
PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this); PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this);
Size IMainWindow.ClientSize => this.ClientSize; Size IMainWindow.ClientSize => ClientSize;
Size? IMainWindow.FrameSize => this.FrameSize; Size? IMainWindow.FrameSize => FrameSize;
WindowState IMainWindow.State => this.WindowState; WindowState IMainWindow.State => WindowState;
private void InitializeComponent(IMainWindow? window) private void InitializeComponent(IMainWindow? window)
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
this.DataContext = new MainViewModel<MainWindow>(this); DataContext = new MainViewModel<MainWindow>(this);
if (window is not null) if (window is not null)
{ {
this.MainControl.Reload(window.Model); this.MainController.Reload(window.Model);
this.WindowStartupLocation = WindowStartupLocation.Manual; WindowStartupLocation = WindowStartupLocation.Manual;
this.WindowState = window.State; WindowState = window.State;
this.Position = window.Position; Position = window.Position;
this.FrameSize = window.FrameSize; FrameSize = window.FrameSize;
this.ClientSize = window.ClientSize; ClientSize = window.ClientSize;
} }
} }
} }

View File

@ -3,60 +3,60 @@ using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using MvvmGen;
using ReactiveUI;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels
{ {
internal record SystemDetail(string Key, string Value); internal record SystemDetail(string Key, string Value);
internal sealed class AboutViewModel : ReactiveObject [ViewModel]
internal sealed partial class AboutViewModel
{ {
private readonly IBitmap _computerImage; private readonly IBitmap _computerImage;
private readonly Boolean _darkTheme; private readonly bool _darkTheme;
public IBitmap ComputerImage => _computerImage; public IBitmap ComputerImage => _computerImage;
public IReadOnlyList<SystemDetail> SystemDetails { get; } = new[] public IReadOnlyList<SystemDetail> SystemDetails { get; } =
{ new[]
new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()), {
new SystemDetail("OS", RuntimeInformation.OSDescription), new SystemDetail("Number of Cores", Environment.ProcessorCount.ToString()),
new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()), new SystemDetail("OS", RuntimeInformation.OSDescription),
new SystemDetail("OS Version", Environment.OSVersion.ToString()), new SystemDetail("OS Arch", RuntimeInformation.OSArchitecture.ToString()),
new SystemDetail("Computer", Environment.MachineName), new SystemDetail("OS Version", Environment.OSVersion.ToString()),
new SystemDetail("User", Environment.UserName), new SystemDetail("Computer", Environment.MachineName),
new SystemDetail("System Path", Environment.SystemDirectory), new SystemDetail("User", Environment.UserName),
new SystemDetail("Current Path", Environment.CurrentDirectory), new SystemDetail("System Path", Environment.SystemDirectory),
new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()), new SystemDetail("Current Path", Environment.CurrentDirectory),
new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription), new SystemDetail("Process Arch", RuntimeInformation.ProcessArchitecture.ToString()),
new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()), new SystemDetail("Runtime Name", RuntimeInformation.FrameworkDescription),
new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()), new SystemDetail("Runtime Path", RuntimeEnvironment.GetRuntimeDirectory()),
new SystemDetail("Framework Version", Environment.Version.ToString()), new SystemDetail("Runtime Version", RuntimeEnvironment.GetSystemVersion()),
}; new SystemDetail("Framework Version", Environment.Version.ToString()),
};
private String ComputerImageName private string ComputerImageName
{ {
get get
{ {
if (Utilities.IsWindows) if (Utilities.IsWindows)
return !this._darkTheme ? "windows.png" : "windows_d.png"; return !_darkTheme ? "windows.png" : "windows_d.png";
else if (Utilities.IsOSX) else if (Utilities.IsOSX)
return !this._darkTheme ? "macos.png" : "macos_d.png"; return !_darkTheme ? "macos.png" : "macos_d.png";
else else
return !this._darkTheme ? "linux.png" : "linux_d.png"; return !_darkTheme ? "linux.png" : "linux_d.png";
} }
} }
public AboutViewModel(Boolean darkTheme) public AboutViewModel(bool darkTheme) : this()
{ {
this._darkTheme = darkTheme; _darkTheme = darkTheme;
this._computerImage = Utilities.GetImageFromResources(this.ComputerImageName); _computerImage = Utilities.GetImageFromResources(ComputerImageName);
} }
~AboutViewModel() ~AboutViewModel()
{ {
this._computerImage.Dispose(); _computerImage.Dispose();
} }
} }
} }

View File

@ -1,100 +1,86 @@
using System; using System;
using System.Reactive;
using Avalonia.Controls; using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using MvvmGen;
using ReactiveUI;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels
{ {
internal abstract class ApplicationModelBase : ReactiveObject [ViewModel]
internal abstract partial class ApplicationModelBase
{ {
private readonly IThemeSwitch _themeSwitch; private readonly IThemeSwitch _themeSwitch;
private Boolean _aboutEnable = true;
private Boolean _defaultLightEnable = false;
private Boolean _defaultDarkEnable = false;
private Boolean _fluentLightEnable = false;
private Boolean _fluentDarkEnable = false;
public Boolean AboutEnabled [Property]
private bool _aboutEnabled = true;
[Property]
private bool _defaultLightEnabled = false;
[Property]
private bool _defaultDarkEnabled = false;
[Property]
private bool _fluentLightEnabled = false;
[Property]
private bool _fluentDarkEnabled = false;
public ApplicationModelBase(IThemeSwitch themeSwitch) : this()
{ {
get => this._aboutEnable; _themeSwitch = themeSwitch;
set => this.RaiseAndSetIfChanged(ref this._aboutEnable, value); IntializeTheme(themeSwitch.Current);
} }
public Boolean DefaultLightEnabled [Command]
{ protected abstract void HelpAbout();
get => this._defaultLightEnable;
set => this.RaiseAndSetIfChanged(ref this._defaultLightEnable, value);
}
public Boolean DefaultDarkEnabled [Command]
{ protected abstract void DefaultLight();
get => this._defaultDarkEnable;
set => this.RaiseAndSetIfChanged(ref this._defaultDarkEnable, value);
}
public Boolean FluentLightEnabled [Command]
{ protected abstract void DefaultDark();
get => this._fluentLightEnable;
set => this.RaiseAndSetIfChanged(ref this._fluentLightEnable, value);
}
public Boolean FluentDarkEnabled [Command]
{ protected abstract void FluentLight();
get => this._fluentDarkEnable;
set => this.RaiseAndSetIfChanged(ref this._fluentDarkEnable, value);
}
public ReactiveCommand<Unit, Unit> FileExitCommand { get; } [Command]
protected abstract void FluentDark();
public ApplicationModelBase(IThemeSwitch themeSwitch)
{
this._themeSwitch = themeSwitch;
this.IntializeTheme(themeSwitch.Current);
this.FileExitCommand = ReactiveCommand.Create(RunFileExit);
}
public abstract void HelpAboutMethod();
public abstract void DefaultLightMethod();
public abstract void DefaultDarkMethod();
public abstract void FluentLightMethod();
public abstract void FluentDarkMethod();
protected async void RunHelpAbout(Window currentWindow) protected async void RunHelpAbout(Window currentWindow)
{ {
if (this.AboutEnabled) if (AboutEnabled)
try try
{ {
this.AboutEnabled = false; AboutEnabled = false;
await new AboutWindow(IsDarkTheme(this._themeSwitch.Current)).ShowDialog(currentWindow); await new AboutWindow(IsDarkTheme(_themeSwitch.Current)).ShowDialog(currentWindow);
} }
finally finally
{ {
this.AboutEnabled = true; AboutEnabled = true;
} }
} }
protected void SetTheme(ApplicationTheme theme) protected void SetTheme(ApplicationTheme theme)
{ {
this.IntializeTheme(theme); IntializeTheme(theme);
this._themeSwitch.ChangeTheme(theme); _themeSwitch.ChangeTheme(theme);
} }
private void RunFileExit() => Environment.Exit(0); [Command]
private void FileExit() => Environment.Exit(0);
private void IntializeTheme(ApplicationTheme theme) private void IntializeTheme(ApplicationTheme theme)
{ {
this.DefaultLightEnabled = theme != ApplicationTheme.SimpleLight; DefaultLightEnabled = theme != ApplicationTheme.SimpleLight;
this.DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark; DefaultDarkEnabled = theme != ApplicationTheme.SimpleDark;
this.FluentLightEnabled = theme != ApplicationTheme.FluentLight; FluentLightEnabled = theme != ApplicationTheme.FluentLight;
this.FluentDarkEnabled = theme != ApplicationTheme.FluentDark; FluentDarkEnabled = theme != ApplicationTheme.FluentDark;
} }
private static Boolean IsDarkTheme(ApplicationTheme? theme) private static bool IsDarkTheme(ApplicationTheme? theme) =>
=> theme switch theme switch
{ {
ApplicationTheme.SimpleDark => true, ApplicationTheme.SimpleDark => true,
ApplicationTheme.FluentDark => true, ApplicationTheme.FluentDark => true,

View File

@ -1,24 +1,27 @@
using Avalonia.Controls; using Avalonia.Controls;
using AvaloniaCoreRTDemo.Interfaces; using AvaloniaCoreRTDemo.Interfaces;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Windows.ViewModels namespace AvaloniaCoreRTDemo.Windows.ViewModels
{ {
internal sealed class MainViewModel<TWindow> : ApplicationModelBase internal sealed class MainViewModel<TWindow> : ApplicationModelBase where TWindow : Window, IMainWindow
where TWindow : Window, IMainWindow
{ {
private TWindow _window; private TWindow _window;
public MainViewModel(TWindow window) public MainViewModel(TWindow window) : base(window.ThemeSwitch)
: base(window.ThemeSwitch)
{ {
this._window = window; _window = window;
} }
public override void HelpAboutMethod() => base.RunHelpAbout(this._window); protected override void HelpAbout() => RunHelpAbout(_window);
public override void DefaultLightMethod() => base.SetTheme(ApplicationTheme.SimpleLight);
public override void DefaultDarkMethod() => base.SetTheme(ApplicationTheme.SimpleDark); protected override void DefaultLight() => SetTheme(ApplicationTheme.SimpleLight);
public override void FluentLightMethod() => base.SetTheme(ApplicationTheme.FluentLight);
public override void FluentDarkMethod() => base.SetTheme(ApplicationTheme.FluentDark); protected override void DefaultDark() => SetTheme(ApplicationTheme.SimpleDark);
protected override void FluentLight() => SetTheme(ApplicationTheme.FluentLight);
protected override void FluentDark() => SetTheme(ApplicationTheme.FluentDark);
} }
} }