U:调整调用方式和兼容性

This commit is contained in:
jimmy committed 2025-12-15 13:37:11 +08:00
1 parent 433e206d45
commit 4ec76b7855
50 files changed
+5592 -47

No files matched your search

+194
View File
@@ -0,0 +1,194 @@
# 01 - 最小 WPF 应用
这是一个最简单的 Sharp WPF 应用示例,演示了框架的基础用法。
## 🎯 学习目标
- 了解 Sharp 框架的基本结构
- 掌握 MVVM 模式(ViewModelBase)
- 使用 Commands(RelayCommand, AsyncCommand)
- 使用对话框服务(IDialogService)
- 理解 Quick Start 配置方式
## 📦 使用的模块
- **Sharp.Common** - Result<T>, 基础工具
- **Sharp.Config** - 配置管理
- **Sharp.Wpf** - MVVM 基础设施
## 🏗️ 项目结构
```
01-MinimalWpfApp/
├── App.xaml # 应用程序入口
├── App.xaml.cs # Quick Start 配置
├── MainWindow.xaml # 主窗口界面
├── MainWindow.xaml.cs # 主窗口代码隐藏
├── ViewModels/
│ └── MainViewModel.cs # 主窗口 ViewModel
├── appsettings.json # 配置文件
└── README.md # 本文件
```
## 🚀 快速运行
```bash
cd examples/01-MinimalWpfApp
dotnet run
```
## 📝 核心代码讲解
### 1. App.xaml.cs - 应用启动
```csharp
protected override void OnStartup(StartupEventArgs e)
{
var services = new ServiceCollection();
// 一行添加基础服务(配置、日志、缓存)
services.AddSharpEssentials();
// 一行添加 WPF 服务(对话框、调度器、导航、主题)
services.AddSharpWpf();
// 注册 ViewModel 和 Window
services.AddViewModel<MainViewModel>();
services.AddTransient<MainWindow>();
// 构建服务提供者
_serviceProvider = services.BuildServiceProvider();
// 显示主窗口
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
}
```
**关键点**:
- `AddSharpEssentials()` - 自动配置 Config + Log + Cache
- `AddSharpWpf()` - 自动注册 WPF 服务
- 无需手动配置,使用约定优于配置
### 2. MainViewModel.cs - ViewModel 示例
```csharp
public class MainViewModel : ViewModelBase
{
private readonly IDialogService _dialogService;
private string _message = "Hello, Sharp!";
private int _counter = 0;
public string Message
{
get => _message;
set => SetProperty(ref _message, value);
}
public int Counter
{
get => _counter;
set => SetProperty(ref _counter, value);
}
// 同步命令
public ICommand IncrementCommand { get; }
// 异步命令
public ICommand ShowDialogCommand { get; }
public MainViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
// RelayCommand - 同步操作
IncrementCommand = new RelayCommand(() => {
Counter++;
Message = $"你点击了 {Counter} 次";
});
// AsyncCommand - 异步操作
ShowDialogCommand = new AsyncCommand(async (ct) => {
IsBusy = true; // 显示加载状态
// 模拟耗时操作
await Task.Delay(1000, ct);
_dialogService.ShowMessage($"当前计数: {Counter}", "提示");
IsBusy = false;
});
}
}
```
**关键点**:
- 继承 `ViewModelBase` 获得 INotifyPropertyChanged
- 使用 `SetProperty()` 自动触发属性变化通知
- `IsBusy` 属性用于显示加载状态
- `RelayCommand` 用于同步操作
- `AsyncCommand` 用于异步操作(支持取消)
### 3. MainWindow.xaml - 界面绑定
```xml
<Window ...>
<Window.DataContext>
<!-- ViewModel 会通过 DI 自动注入 -->
</Window.DataContext>
<StackPanel Margin="20">
<!-- 绑定属性 -->
<TextBlock Text="{Binding Message}" FontSize="24"/>
<!-- 绑定命令 -->
<Button Content="点击我" Command="{Binding IncrementCommand}"/>
<!-- 异步命令 -->
<Button Content="显示对话框" Command="{Binding ShowDialogCommand}"/>
<!-- 显示加载状态 -->
<TextBlock Text="加载中..." Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibilityConverter}}"/>
</StackPanel>
</Window>
```
**关键点**:
- 使用 `{Binding}` 绑定 ViewModel 属性
- Command 绑定到 ICommand 属性
- 使用内置转换器(BoolToVisibilityConverter)
## 🎓 练习建议
### 练习1:添加新属性
在 MainViewModel 中添加一个 `Name` 属性,并在界面上显示。
### 练习2:添加清零按钮
添加一个 `ResetCommand`,点击后将 `Counter` 重置为 0。
### 练习3:使用对话框确认
在 ResetCommand 中,先弹出确认对话框,用户确认后再清零。
### 练习4:尝试 Result<T>
修改 ShowDialogCommand,使用 `Result.Try()` 包装可能出错的代码。
## 📚 延伸阅读
- [Sharp.Wpf README](../../src/Sharp/Wpf/README.md) - WPF 模块完整文档
- [QUICKSTART.md](../../src/Sharp/QUICKSTART.md) - 快速启动指南
- 下一个示例:[02-WpfWithDatabase](../02-WpfWithDatabase/README.md)
## ❓ 常见问题
**Q: 为什么 MainWindow 不需要手动设置 DataContext?**
A: 通过 DI 容器获取 Window 时,会自动注入对应的 ViewModel。
**Q: IsBusy 是在哪里定义的?**
A: `IsBusy` 是 `ViewModelBase` 的内置属性,用于显示加载状态。
**Q: 可以不用 DI 吗?**
A: 可以,但不推荐。使用 DI 可以更好地管理依赖关系,便于测试。
---
**开始编码吧!** 🚀