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,13 +1,18 @@
<Application xmlns="https://github.com/avaloniaui" <Application
x:Class="AvaloniaCoreRTDemo.App"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
RequestedThemeVariant="Light"
x:Class="AvaloniaCoreRTDemo.App"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels1:ApplicationModelBase"> x:DataType="viewModels1:ApplicationModelBase"
RequestedThemeVariant="Light">
<NativeMenu.Menu> <NativeMenu.Menu>
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="About" Gesture="cmd+b" IsEnabled="{Binding AboutEnabled}" Command="{Binding HelpAboutMethod}"/> <NativeMenuItem
Command="{Binding HelpAboutCommand}"
Gesture="cmd+b"
Header="About"
IsEnabled="{Binding AboutEnabled}" />
</NativeMenu> </NativeMenu>
</NativeMenu.Menu> </NativeMenu.Menu>
<Application.Resources> <Application.Resources>

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
x:Class="AvaloniaCoreRTDemo.Controls.MainControl"
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"
xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels" xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Controls.MainControl" d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels:MainControlViewModel"> x:DataType="viewModels:MainControlViewModel"
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*" Margin="32"> mc:Ignorable="d">
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" TextAlignment="Center" Margin="0,6">Welcome to Avalonia UI + NativeAOT!</TextBlock> <Grid
<Image Grid.Row="1" Grid.Column="0" Stretch="None" Source="{Binding DotNetImage}"/> Margin="32"
<Image Grid.Row="1" Grid.Column="1" Stretch="None" Source="{Binding AvaloniaImage}"/> ColumnDefinitions="*,*"
<TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Watermark="Type here" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Text}"/> 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> </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,19 +1,49 @@
<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
x:Class="AvaloniaCoreRTDemo.Windows.AboutWindow"
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"
xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
mc:Ignorable="d" x:Class="AvaloniaCoreRTDemo.Windows.AboutWindow" d:DesignWidth="640" d:DesignHeight="256"
WindowState="Normal" WindowStartupLocation="CenterOwner" Height="256" MaxWidth="840"
SizeToContent="Width"
Title="About" Title="About"
CanResize="false" ShowInTaskbar="False" Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico" Height="256"
MaxWidth="840"
d:DesignHeight="256"
d:DesignWidth="640"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels:AboutViewModel"> x:DataType="viewModels:AboutViewModel"
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ColumnDefinitions="Auto,*"> CanResize="false"
<Image Margin="0, 60" Grid.Column="0" Stretch="None" Source="{Binding ComputerImage}" VerticalAlignment="Top" HorizontalAlignment="Left"> Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico"
</Image> ShowInTaskbar="False"
<DataGrid Grid.Column="1" Items="{Binding SystemDetails}" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" HeadersVisibility="None"> SizeToContent="Width"
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> <DataGrid.Columns>
<DataGridTextColumn Header="Key" Binding="{Binding Key, x:DataType=viewModels:SystemDetail}" FontWeight="Bold" /> <DataGridTextColumn
<DataGridTextColumn Header="Value" Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" /> Binding="{Binding Key, x:DataType=viewModels:SystemDetail}"
FontWeight="Bold"
Header="Key" />
<DataGridTextColumn Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" Header="Value" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</Grid> </Grid>

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,10 +1,23 @@
<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
x:Class="AvaloniaCoreRTDemo.Windows.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:AvaloniaCoreRTDemo.Controls" xmlns:controls="clr-namespace:AvaloniaCoreRTDemo.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels" xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Windows.MainWindow" Title="AvaloniaCoreRTDemo"
Width="640" Height="480" WindowStartupLocation="CenterScreen" Title="AvaloniaCoreRTDemo" Icon="avares://AvaloniaCoreRTDemo/Assets/app.ico" MinWidth="400" MinHeight="350" Width="640"
Height="480"
MinWidth="400"
MinHeight="350"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels1:ApplicationModelBase"> 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" />
@ -14,18 +27,37 @@
<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,22 +3,22 @@ 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("Number of Cores", Environment.ProcessorCount.ToString()),
new SystemDetail("OS", RuntimeInformation.OSDescription), new SystemDetail("OS", RuntimeInformation.OSDescription),
@ -35,28 +35,28 @@ namespace AvaloniaCoreRTDemo.Windows.ViewModels
new SystemDetail("Framework Version", Environment.Version.ToString()), 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);
} }
} }