U:调整调用方式和兼容性
This commit is contained in:
1 parent
433e206d45
commit
4ec76b7855
50 files changed
+5592
-47
No files matched your search
@@ -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 可以更好地管理依赖关系,便于测试。
|
||||
|
||||
---
|
||||
|
||||
**开始编码吧!** 🚀
|
||||
Reference in new issue
Block a user