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

View File

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

View File

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

View File

@ -11,6 +11,7 @@
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<SelfContained>true</SelfContained>
<ImplicitUsing>enable</ImplicitUsing>
</PropertyGroup>
<PropertyGroup>
@ -50,13 +51,16 @@
<PackageReference Include="Avalonia" Version="11.0.0-*" />
<PackageReference Include="Avalonia.Desktop" 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.Fluent" Version="11.0.0-*" />
<!--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-*" />
<!--Condition below is needed to generate macOS App only.-->
<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>
<!-- 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"
xmlns:viewModels="clr-namespace:AvaloniaCoreRTDemo.Controls.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Controls.MainControl"
x:CompileBindings="True"
x:DataType="viewModels:MainControlViewModel">
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*" Margin="32">
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" TextAlignment="Center" Margin="0,6">Welcome to Avalonia UI + NativeAOT!</TextBlock>
<Image Grid.Row="1" Grid.Column="0" Stretch="None" Source="{Binding DotNetImage}"/>
<Image Grid.Row="1" Grid.Column="1" Stretch="None" Source="{Binding AvaloniaImage}"/>
<TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Watermark="Type here" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Text}"/>
</Grid>
<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"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
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>

View File

@ -9,18 +9,18 @@ namespace AvaloniaCoreRTDemo.Controls
{
public MainControl()
{
this.InitializeComponent();
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
this.DataContext = new MainControlViewModel();
DataContext = new MainControlViewModel();
}
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 ReactiveUI;
using Avalonia.Media.Imaging;
using MvvmGen;
namespace AvaloniaCoreRTDemo.Controls.ViewModels
{
internal sealed class MainControlViewModel : ReactiveObject, IMainWindowState
[ViewModel]
internal sealed partial class MainControlViewModel : IMainWindowState
{
private readonly IBitmap _dotNetImage;
private readonly IBitmap _avaloniaImage;
private IBitmap _dotNetImage;
private IBitmap _avaloniaImage;
private Boolean _unloadable = false;
private bool _unloadable = false;
public IBitmap DotNetImage => this._dotNetImage;
public IBitmap AvaloniaImage => this._avaloniaImage;
public String? Text { get; set; }
public IBitmap DotNetImage => _dotNetImage;
public IBitmap AvaloniaImage => _avaloniaImage;
public string? Text { get; set; }
public MainControlViewModel()
partial void OnInitialize()
{
this._dotNetImage = Utilities.GetImageFromFile("dotnet.png");
this._avaloniaImage = Utilities.GetImageFromFile("avalonia.png");
_dotNetImage = Utilities.GetImageFromFile("dotnet.png");
_avaloniaImage = Utilities.GetImageFromFile("avalonia.png");
}
public MainControlViewModel(IMainWindowState state)
public MainControlViewModel(IMainWindowState state) : this()
{
this._avaloniaImage = state.AvaloniaImage;
this._dotNetImage = state.DotNetImage;
this.Text = state.Text;
_avaloniaImage = state.AvaloniaImage;
_dotNetImage = state.DotNetImage;
Text = state.Text;
state.SetUnloadable();
}
~MainControlViewModel()
{
if (!this._unloadable)
if (!_unloadable)
{
this._dotNetImage.Dispose();
this._avaloniaImage.Dispose();
_dotNetImage.Dispose();
_avaloniaImage.Dispose();
}
}
void IMainWindowState.SetUnloadable()
{
this._unloadable = true;
_unloadable = true;
}
}
}

View File

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

View File

@ -11,10 +11,10 @@ namespace AvaloniaCoreRTDemo
{
internal static class Utilities
{
public static readonly Boolean IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static readonly Boolean IsOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
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>();
using var assetStream = assetLoader.Open(new Uri($"avares://AvaloniaCoreRTDemo/Images/{fileName}"));
@ -27,12 +27,12 @@ namespace AvaloniaCoreRTDemo
return window.Position;
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);
}
}
public static Bitmap GetImageFromFile(String path)
public static Bitmap GetImageFromFile(string path)
{
try
{
@ -44,7 +44,6 @@ namespace AvaloniaCoreRTDemo
}
}
private static String GetImageFullPath(String fileName)
=> Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
private static string GetImageFullPath(string 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"
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"
CanResize="false" ShowInTaskbar="False" Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico"
x:CompileBindings="True"
x:DataType="viewModels:AboutViewModel">
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ColumnDefinitions="Auto,*">
<Image Margin="0, 60" Grid.Column="0" Stretch="None" Source="{Binding ComputerImage}" VerticalAlignment="Top" HorizontalAlignment="Left">
</Image>
<DataGrid Grid.Column="1" Items="{Binding SystemDetails}" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" HeadersVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Header="Key" Binding="{Binding Key, x:DataType=viewModels:SystemDetail}" FontWeight="Bold" />
<DataGridTextColumn Header="Value" Binding="{Binding Value, x:DataType=viewModels:SystemDetail}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
<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"
Title="About"
Height="256"
MaxWidth="840"
d:DesignHeight="256"
d:DesignWidth="640"
x:CompileBindings="True"
x:DataType="viewModels:AboutViewModel"
CanResize="false"
Icon="avares://AvaloniaCoreRTDemo/Assets/about.ico"
ShowInTaskbar="False"
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>
<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>

View File

@ -10,14 +10,14 @@ namespace AvaloniaCoreRTDemo.Windows
{
public sealed partial class AboutWindow : Window
{
private readonly Boolean _darkTheme;
private readonly bool _darkTheme;
public AboutWindow() : this(false) { }
public AboutWindow(Boolean darkTheme)
public AboutWindow(bool darkTheme)
{
this._darkTheme = darkTheme;
this.InitializeComponent();
_darkTheme = darkTheme;
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
@ -26,7 +26,7 @@ namespace AvaloniaCoreRTDemo.Windows
private void InitializeComponent()
{
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"
xmlns:controls="clr-namespace:AvaloniaCoreRTDemo.Controls"
xmlns:viewModels1="clr-namespace:AvaloniaCoreRTDemo.Windows.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="AvaloniaCoreRTDemo.Windows.MainWindow"
Width="640" Height="480" WindowStartupLocation="CenterScreen" Title="AvaloniaCoreRTDemo" Icon="avares://AvaloniaCoreRTDemo/Assets/app.ico" MinWidth="400" MinHeight="350"
x:CompileBindings="True"
x:DataType="viewModels1:ApplicationModelBase">
<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:d="http://schemas.microsoft.com/expression/blend/2008"
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>
<NativeMenuBar DockPanel.Dock="Top" />
<controls:MainControl Name="MainControl"/>
<controls:MainControl Name="MainControl" />
</DockPanel>
<NativeMenu.Menu>
<NativeMenu>
<NativeMenuItem Header="File">
<NativeMenuItem.Menu>
<NativeMenu>
<NativeMenuItem Header="Exit" Gesture="cmd+e" Command="{Binding FileExitCommand}"/>
<NativeMenuItem Header="About" Gesture="cmd+b" IsEnabled="{Binding AboutEnabled}" Command="{Binding HelpAboutMethod}"/>
<NativeMenuItem
Command="{Binding FileExitCommand}"
Gesture="cmd+e"
Header="Exit" />
<NativeMenuItem
Command="{Binding HelpAboutCommand}"
Gesture="cmd+b"
Header="About"
IsEnabled="{Binding AboutEnabled}" />
</NativeMenu>
</NativeMenuItem.Menu>
</NativeMenuItem>
<NativeMenuItem Header="Theme">
<NativeMenuItem.Menu>
<NativeMenu>
<NativeMenuItem Header="Default Light" IsEnabled="{Binding DefaultLightEnabled}" Command="{Binding DefaultLightMethod}"/>
<NativeMenuItem Header="Default Dark" IsEnabled="{Binding DefaultDarkEnabled}" Command="{Binding DefaultDarkMethod}"/>
<NativeMenuItem Header="Fluent Light" IsEnabled="{Binding FluentLightEnabled}" Command="{Binding FluentLightMethod}"/>
<NativeMenuItem Header="Fluent Dark" IsEnabled="{Binding FluentDarkEnabled}" Command="{Binding FluentDarkMethod}"/>
<NativeMenuItem
Command="{Binding DefaultLightCommand}"
Header="Default Light"
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>
</NativeMenuItem.Menu>
</NativeMenuItem>

View File

@ -10,38 +10,39 @@ namespace AvaloniaCoreRTDemo.Windows
{
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(IMainWindow? window)
{
this.InitializeComponent(window);
InitializeComponent(window);
#if DEBUG
this.AttachDevTools();
#endif
}
IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)this._app!;
IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainControl.DataContext!;
IThemeSwitch IMainWindow.ThemeSwitch => (IThemeSwitch)_app!;
IMainWindowState IMainWindow.Model => (IMainWindowState)this.MainController.DataContext!;
PixelPoint IMainWindow.Position => Utilities.GetWindowPosition(this);
Size IMainWindow.ClientSize => this.ClientSize;
Size? IMainWindow.FrameSize => this.FrameSize;
WindowState IMainWindow.State => this.WindowState;
Size IMainWindow.ClientSize => ClientSize;
Size? IMainWindow.FrameSize => FrameSize;
WindowState IMainWindow.State => WindowState;
private void InitializeComponent(IMainWindow? window)
{
AvaloniaXamlLoader.Load(this);
this.DataContext = new MainViewModel<MainWindow>(this);
DataContext = new MainViewModel<MainWindow>(this);
if (window is not null)
{
this.MainControl.Reload(window.Model);
this.WindowStartupLocation = WindowStartupLocation.Manual;
this.WindowState = window.State;
this.Position = window.Position;
this.FrameSize = window.FrameSize;
this.ClientSize = window.ClientSize;
this.MainController.Reload(window.Model);
WindowStartupLocation = WindowStartupLocation.Manual;
WindowState = window.State;
Position = window.Position;
FrameSize = window.FrameSize;
ClientSize = window.ClientSize;
}
}
}

View File

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

View File

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

View File

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