diff --git a/App.config "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/App.config" similarity index 100% rename from App.config rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/App.config" diff --git a/AppConfig.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/AppConfig.cs" similarity index 100% rename from AppConfig.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/AppConfig.cs" diff --git a/File.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/File.cs" similarity index 100% rename from File.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/File.cs" diff --git a/FileDropAdmin.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/FileDropAdmin.cs" similarity index 100% rename from FileDropAdmin.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/FileDropAdmin.cs" diff --git a/Form.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.Designer.cs" similarity index 100% rename from Form.Designer.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.Designer.cs" diff --git a/Form.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.cs" similarity index 100% rename from Form.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.cs" diff --git a/Form.resx "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.resx" similarity index 100% rename from Form.resx rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.resx" diff --git a/Icon.ico "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Icon.ico" similarity index 100% rename from Icon.ico rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Icon.ico" diff --git a/LICENSE "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/LICENSE" similarity index 100% rename from LICENSE rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/LICENSE" diff --git a/Other.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Other.cs" similarity index 100% rename from Other.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Other.cs" diff --git a/Program.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Program.cs" similarity index 100% rename from Program.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Program.cs" diff --git a/Properties/Resources.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.Designer.cs" similarity index 100% rename from Properties/Resources.Designer.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.Designer.cs" diff --git a/Properties/Resources.resx "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.resx" similarity index 100% rename from Properties/Resources.resx rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.resx" diff --git a/Properties/Settings.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.Designer.cs" similarity index 100% rename from Properties/Settings.Designer.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.Designer.cs" diff --git a/Properties/Settings.settings "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.settings" similarity index 100% rename from Properties/Settings.settings rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.settings" diff --git a/Registry.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Registry.cs" similarity index 100% rename from Registry.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Registry.cs" diff --git a/WebClient.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/WebClient.cs" similarity index 100% rename from WebClient.cs rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/WebClient.cs" diff --git a/app.manifest "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/app.manifest" similarity index 100% rename from app.manifest rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/app.manifest" diff --git a/syspin.dll "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/syspin.dll" similarity index 100% rename from syspin.dll rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/syspin.dll" diff --git "a/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj" similarity index 100% rename from "\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj" rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj" diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config" new file mode 100644 index 0000000..10b1fb1 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config" @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest" new file mode 100644 index 0000000..75fadaf --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest" @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PerMonitorV2 + true + + + + + + + + + + + diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml" new file mode 100644 index 0000000..23a88b1 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml" @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs" new file mode 100644 index 0000000..05dd157 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs" @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +using Xiu2.TileTool.Core; + +namespace Xiu2.TileTool +{ + public partial class App : Application + { + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + // 判断系统版本 + if (Environment.OSVersion.Version.Major != 10) + { + _ = MessageBox.Show($"{AppInfo.Main.AppName}仅支持 Windows10 系统!", "错误", MessageBoxButton.OK); + Shutdown(); + } + } + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs" new file mode 100644 index 0000000..84ef534 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs" @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Xiu2.TileTool.Core +{ + /// + /// 包含应用程序的一般信息。 + /// + internal class AppInfo + { + /// + /// 获取当前应用程序的一般信息。 + /// + public static AppInfo Main { get; } = new AppInfo(Assembly.GetEntryAssembly()!); + + public AppInfo(Assembly assembly) + { + AppName = assembly.GetCustomAttribute()?.Product + ?? assembly.GetCustomAttribute()!.Title; + Version = assembly.GetCustomAttribute()!.InformationalVersion; + Author = assembly.GetCustomAttribute()!.Company; + } + + /// + /// 获取应用名称。 + /// + public string AppName { get; } + + /// + /// 获取版本号(可能带预览标签)。 + /// + public string Version { get; } + + /// + /// 获取作者名。 + /// + public string Author { get; } + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs" new file mode 100644 index 0000000..09c32be --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs" @@ -0,0 +1,86 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using Xiu2.TileTool.Core; + +namespace Xiu2.TileTool +{ + internal static class Program + { + [STAThread] + static void Main(string[] args) + { + // 启动前一个进程实例。 + Mutex? newMutex = null; + try + { +#pragma warning disable IDE0067 // 丢失范围之前释放对象 + newMutex = new Mutex(true, "a8851f5e-cbb5-4466-bd72-d95c9bea4dea", out bool createdNew); +#pragma warning restore IDE0067 // 丢失范围之前释放对象 + if (!createdNew) + { + if (args.Length > 0 && args[0] != "") + { + // 右键菜单启动:杀掉已存在的进程。 + KillSameNameProcess(); + } + else + { + // 用户双击启动,打开之前已打开的窗口。 + var current = Process.GetCurrentProcess(); + var process = Process.GetProcessesByName(current.ProcessName).FirstOrDefault(x => x.Id != current.Id); + if (process != null) + { + var hwnd = process.MainWindowHandle; + ShowWindow(hwnd, 9); + SetForegroundWindow(hwnd); + return; + } + } + } + } + catch (Exception) + { + // 忽略任何多实例处理相关的异常。 + } + + // 启动自己。 + var app = new App(); + app.InitializeComponent(); + app.Run(); + } + + /// + /// 结束同名进程。 + /// + private static void KillSameNameProcess() + { + var name = AppInfo.Main.AppName; + // 获取当前进程信息。 + Process currentProcess = Process.GetCurrentProcess(); + // 获取同名进程信息。 + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + // 判断该进程主窗口标题是否含有 XXX 字符串。 + if (process.MainWindowTitle.Contains(name)) + { + // 如果不是当前进程,就结束它。 + if (process.Id != currentProcess.Id) + { + process.Kill(); + } + } + } + } + + [DllImport("user32.dll")] + private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow); + + [DllImport("USER32.DLL")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs" new file mode 100644 index 0000000..8b5504e --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs" @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml" new file mode 100644 index 0000000..e95ae8a --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml" @@ -0,0 +1,43 @@ + + + #0B6AB4 + #2286CC + #014696 + White + #999999 + #2B2B2B + White + #999999 + #2B2B2B + #353536 + #353536 + #353536 + #353536 + #353536 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml" new file mode 100644 index 0000000..7957486 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml" @@ -0,0 +1,67 @@ + + + + + + + + + \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml" new file mode 100644 index 0000000..5bc4ab9 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml" @@ -0,0 +1,48 @@ + + + + + + + + + + + \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml" new file mode 100644 index 0000000..4ccd3a9 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml" @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs" new file mode 100644 index 0000000..06fbbc6 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs" @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +// 来源:https://github.com/walterlv/Walterlv.Packages/blob/master/src/Frameworks/Walterlv.Windows.Framework/ComponentModel/BindableObject.cs + +namespace Xiu2.TileTool.UIFramework +{ + /// + /// 表示可绑定的对象,在此类型的派生类中按约定定义的属性支持绑定。 + /// + public abstract class BindableObject : INotifyPropertyChanged + { + /// + /// 当此实例中的任何一个具有更改通知的属性值改变时发生。 + /// 派生类可以通过调用 来引发此事件。 + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// 当具有更改通知的属性值改变时发生。 + /// + /// 属性名称。不需要手动传入,会自动根据所在属性的方法名设置此参数值。 + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + /// + /// 修改一个具有更改通知的属性值,并对外报告值的改变。 + /// + /// 值的类型。 + /// 要修改的字段引用。 + /// 要修改的字段的新值。 + /// 属性名称。不需要手动传入,会自动根据所在属性的方法名设置此参数值。 + /// 如果值发生了更改,则返回 true;否则返回 false。 + protected bool SetValue(ref T field, T value, [CallerMemberName] string? propertyName = null) + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(propertyName); + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs" new file mode 100644 index 0000000..7f49782 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs" @@ -0,0 +1,121 @@ +using System; +using System.Diagnostics.Contracts; +using System.Windows; + +// 来源:https://github.com/walterlv/Walterlv.Packages/blob/master/src/Frameworks/Walterlv.Windows.Framework/Windows/Navigating/NavigationItem.cs + +namespace Xiu2.TileTool.UIFramework +{ + /// + /// 为 Master-Detail 布局型导航提供通用的 ViewModel。 + /// + public class NavigationItem : BindableObject + { + private readonly Func _viewCreator; + private readonly Func _viewModelCreator; + private UIElement? _view; + private object? _viewModel; + + /// + /// 创建 的新实例。 + /// + /// 创建 View 的方法。 + /// 创建 ViewModel 的方法。 + /// 导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航的描述导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航对象的额外属性(为避免额外编写继承自 的类,这里提供一个通用的属性,用于在导航的 ViewModel 上下文中绑定使用)。 + public NavigationItem(Func viewCreator, Func viewModelCreator, + string? title = null, string? description = null, object? data = null) + { + _viewCreator = viewCreator ?? throw new ArgumentNullException(nameof(viewCreator)); + _viewModelCreator = viewModelCreator ?? throw new ArgumentNullException(nameof(viewModelCreator)); + Title = title ?? ""; + Description = description; + Data = data; + } + + /// + /// 导航上下文中的 View。 + /// + public UIElement View => _view ??= _viewCreator(); + + /// + /// 导航上下文中的 ViewModel。 + /// + public object ViewModel => _viewModel ??= _viewModelCreator(); + + /// + /// 导航标题。 + /// + public string? Title { get; } + + /// + /// 导航描述。 + /// + public string? Description { get; } + + /// + /// 导航中附带的额外数据。 + /// + public object? Data { get; } + + /// + /// 将一个 View 和一个 ViewModel 连接起来,组成一个适用于 Master-Detail 布局的通用导航 ViewModel。 + /// + /// View 的类型。 + /// ViewModel 的类型。 + /// 导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航的描述导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航对象的额外属性(为避免额外编写继承自 的类,这里提供一个通用的属性,用于在导航的 ViewModel 上下文中绑定使用)。 + /// 适用于 Master-Detail 布局的通用导航 ViewModel。 + [Pure] + public static NavigationItem Combine( + string? title = null, string? description = null, object? data = null) + where TView : UIElement, new() + where TViewModel : class, new() + => new NavigationItem(() => new TView(), () => new TViewModel(), title, description, data); + } + + /// + /// 为 Master-Detail 布局型导航提供通用的 ViewModel。 + /// + public class NavigationItem : NavigationItem + where TView : UIElement, new() + where TViewModel : class, new() + { + /// + /// 创建 的新实例。 + /// + /// 创建 View 的方法。 + /// 创建 ViewModel 的方法。 + /// 导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航的描述导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航对象的额外属性(为避免额外编写继承自 的类,这里提供一个通用的属性,用于在导航的 ViewModel 上下文中绑定使用)。 + public NavigationItem(Func viewCreator, Func viewModelCreator, + string? title = null, string? description = null, object? data = null) + : base(viewCreator, viewModelCreator, title, description, data) + { + } + + /// + /// 导航上下文中的 View。 + /// + public new TView View => (TView)base.View; + + /// + /// 导航上下文中的 ViewModel。 + /// + public new TViewModel ViewModel => (TViewModel)base.ViewModel; + + /// + /// 将一个 View 和一个 ViewModel 连接起来,组成一个适用于 Master-Detail 布局的通用导航 ViewModel。 + /// + /// 导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航的描述导航的标题(仅提供通用属性,具体使用需在 MVVM 模式中自行绑定 Title 属性)。 + /// 导航对象的额外属性(为避免额外编写继承自 的类,这里提供一个通用的属性,用于在导航的 ViewModel 上下文中绑定使用)。 + /// 适用于 Master-Detail 布局的通用导航 ViewModel。 + [Pure] + public static NavigationItem Combine(string? title = null, string? description = null, object? data = null) + => new NavigationItem(() => new TView(), () => new TViewModel(), title, description, data); + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml" new file mode 100644 index 0000000..5dafda3 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml" @@ -0,0 +1,12 @@ + + + + + diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml.cs" new file mode 100644 index 0000000..2a7ee7c --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutPage.xaml.cs" @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Xiu2.TileTool.Views +{ + /// + /// AboutPage.xaml 的交互逻辑 + /// + public partial class AboutPage : UserControl + { + public AboutPage() + { + InitializeComponent(); + } + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutViewModel.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutViewModel.cs" new file mode 100644 index 0000000..e31da68 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/AboutViewModel.cs" @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Xiu2.TileTool.Views +{ + public class AboutViewModel + { + + } +} diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/EditTilePage.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/EditTilePage.xaml" new file mode 100644 index 0000000..6af3a18 --- /dev/null +++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Views/EditTilePage.xaml" @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + +