diff --git a/JackCraft.I18N.sln b/JackCraft.I18N.sln
index d54c1d3..67aac4c 100644
--- a/JackCraft.I18N.sln
+++ b/JackCraft.I18N.sln
@@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Folder", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{933A9C2F-8C23-4898-A266-780A841218DD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestMvvm", "TestMvvm\TestMvvm.csproj", "{2558A760-25A2-4EA1-8F7B-960C54E1D898}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
{933A9C2F-8C23-4898-A266-780A841218DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{933A9C2F-8C23-4898-A266-780A841218DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{933A9C2F-8C23-4898-A266-780A841218DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2558A760-25A2-4EA1-8F7B-960C54E1D898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2558A760-25A2-4EA1-8F7B-960C54E1D898}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2558A760-25A2-4EA1-8F7B-960C54E1D898}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2558A760-25A2-4EA1-8F7B-960C54E1D898}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/JackCraft.I18N.sln.DotSettings.user b/JackCraft.I18N.sln.DotSettings.user
index b5fbb10..f7290db 100644
--- a/JackCraft.I18N.sln.DotSettings.user
+++ b/JackCraft.I18N.sln.DotSettings.user
@@ -6,5 +6,6 @@
ForceIncluded
ForceIncluded
ForceIncluded
- True
+ True
+ False
True
\ No newline at end of file
diff --git a/TestMvvm/App.axaml b/TestMvvm/App.axaml
new file mode 100644
index 0000000..494d9cc
--- /dev/null
+++ b/TestMvvm/App.axaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestMvvm/App.axaml.cs b/TestMvvm/App.axaml.cs
new file mode 100644
index 0000000..beb945f
--- /dev/null
+++ b/TestMvvm/App.axaml.cs
@@ -0,0 +1,46 @@
+using System.Linq;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Data.Core.Plugins;
+using Avalonia.Markup.Xaml;
+using JackCraft.I18N;
+using TestMvvm.ViewModels;
+using TestMvvm.Views;
+
+namespace TestMvvm;
+
+public class App : Application
+{
+ public static I18NManager I18NManager { get; } = new("TestMvvm.Assets.Resources");
+
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ // Avoid duplicate validations from both Avalonia and the CommunityToolkit.
+ // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
+ DisableAvaloniaDataAnnotationValidation();
+ desktop.MainWindow = new MainWindow
+ {
+ DataContext = new MainWindowViewModel()
+ };
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+
+ private void DisableAvaloniaDataAnnotationValidation()
+ {
+ // Get an array of plugins to remove
+ var dataValidationPluginsToRemove =
+ BindingPlugins.DataValidators.OfType().ToArray();
+
+ // remove each entry found
+ foreach (var plugin in dataValidationPluginsToRemove) BindingPlugins.DataValidators.Remove(plugin);
+ }
+}
\ No newline at end of file
diff --git a/TestMvvm/Assets/Resources.Designer.cs b/TestMvvm/Assets/Resources.Designer.cs
new file mode 100644
index 0000000..b7b5b03
--- /dev/null
+++ b/TestMvvm/Assets/Resources.Designer.cs
@@ -0,0 +1,54 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TestMvvm.Assets {
+ using System;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static System.Resources.ResourceManager resourceMan;
+
+ private static System.Globalization.CultureInfo resourceCulture;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("TestMvvm.Assets.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static string Test1 {
+ get {
+ return ResourceManager.GetString("Test1", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/TestMvvm/Assets/Resources.resx b/TestMvvm/Assets/Resources.resx
new file mode 100644
index 0000000..53651eb
--- /dev/null
+++ b/TestMvvm/Assets/Resources.resx
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ Test1: {0}
+
+
\ No newline at end of file
diff --git a/TestMvvm/Assets/Resources.zh-hans.resx b/TestMvvm/Assets/Resources.zh-hans.resx
new file mode 100644
index 0000000..bbdc8f4
--- /dev/null
+++ b/TestMvvm/Assets/Resources.zh-hans.resx
@@ -0,0 +1,21 @@
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ 测试1: {0}
+
+
\ No newline at end of file
diff --git a/TestMvvm/Assets/avalonia-logo.ico b/TestMvvm/Assets/avalonia-logo.ico
new file mode 100644
index 0000000..da8d49f
Binary files /dev/null and b/TestMvvm/Assets/avalonia-logo.ico differ
diff --git a/TestMvvm/Program.cs b/TestMvvm/Program.cs
new file mode 100644
index 0000000..c942fc5
--- /dev/null
+++ b/TestMvvm/Program.cs
@@ -0,0 +1,26 @@
+using System;
+using Avalonia;
+
+namespace TestMvvm;
+
+internal sealed class Program
+{
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args)
+ {
+ BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+ }
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ {
+ return AppBuilder.Configure()
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+ }
+}
\ No newline at end of file
diff --git a/TestMvvm/TestMvvm.csproj b/TestMvvm/TestMvvm.csproj
new file mode 100644
index 0000000..b7a6db7
--- /dev/null
+++ b/TestMvvm/TestMvvm.csproj
@@ -0,0 +1,47 @@
+
+
+ WinExe
+ net9.0
+ enable
+ true
+ app.manifest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ None
+ All
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
diff --git a/TestMvvm/ViewLocator.cs b/TestMvvm/ViewLocator.cs
new file mode 100644
index 0000000..70daed6
--- /dev/null
+++ b/TestMvvm/ViewLocator.cs
@@ -0,0 +1,27 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using TestMvvm.ViewModels;
+
+namespace TestMvvm;
+
+public class ViewLocator : IDataTemplate
+{
+ public Control? Build(object? param)
+ {
+ if (param is null)
+ return null;
+
+ var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
+ var type = Type.GetType(name);
+
+ if (type != null) return (Control)Activator.CreateInstance(type)!;
+
+ return new TextBlock { Text = "Not Found: " + name };
+ }
+
+ public bool Match(object? data)
+ {
+ return data is ViewModelBase;
+ }
+}
\ No newline at end of file
diff --git a/TestMvvm/ViewModels/MainWindowViewModel.cs b/TestMvvm/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..082a5f9
--- /dev/null
+++ b/TestMvvm/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,29 @@
+using System.Globalization;
+using System.IO;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+namespace TestMvvm.ViewModels;
+
+public partial class MainWindowViewModel : ViewModelBase
+{
+ [ObservableProperty] public string? test = Path.GetRandomFileName();
+
+ [RelayCommand]
+ public void RandomText()
+ {
+ Test = Path.GetRandomFileName();
+ }
+
+ [RelayCommand]
+ public void ChangeToChinese()
+ {
+ App.I18NManager.Culture = new CultureInfo("zh-hans");
+ }
+
+ [RelayCommand]
+ public void ChangeToDefault()
+ {
+ App.I18NManager.Culture = CultureInfo.InvariantCulture;
+ }
+}
\ No newline at end of file
diff --git a/TestMvvm/ViewModels/ViewModelBase.cs b/TestMvvm/ViewModels/ViewModelBase.cs
new file mode 100644
index 0000000..f705002
--- /dev/null
+++ b/TestMvvm/ViewModels/ViewModelBase.cs
@@ -0,0 +1,7 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace TestMvvm.ViewModels;
+
+public class ViewModelBase : ObservableObject
+{
+}
\ No newline at end of file
diff --git a/TestMvvm/Views/MainWindow.axaml b/TestMvvm/Views/MainWindow.axaml
new file mode 100644
index 0000000..c249cbb
--- /dev/null
+++ b/TestMvvm/Views/MainWindow.axaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestMvvm/Views/MainWindow.axaml.cs b/TestMvvm/Views/MainWindow.axaml.cs
new file mode 100644
index 0000000..9298eb1
--- /dev/null
+++ b/TestMvvm/Views/MainWindow.axaml.cs
@@ -0,0 +1,11 @@
+using Avalonia.Controls;
+
+namespace TestMvvm.Views;
+
+public partial class MainWindow : Window
+{
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/TestMvvm/app.manifest b/TestMvvm/app.manifest
new file mode 100644
index 0000000..978bc04
--- /dev/null
+++ b/TestMvvm/app.manifest
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+