A:集成配置文件

This commit is contained in:
jimmy committed 2025-12-28 13:08:42 +08:00
1 parent 54545aad35
commit f610bf5e34
10 files changed
+640 -93

No files matched your search

+3
View File
@@ -127,6 +127,9 @@ namespace Sharp.Demo
services.AddTransient<Sharp.Demo.Views.Windows.DatabaseWindow>(); services.AddTransient<Sharp.Demo.Views.Windows.DatabaseWindow>();
services.AddTransient<Sharp.Demo.Views.Windows.SerialPortWindow>(); services.AddTransient<Sharp.Demo.Views.Windows.SerialPortWindow>();
services.AddTransient<Sharp.Demo.Views.Windows.ProcessTestWindow>(); services.AddTransient<Sharp.Demo.Views.Windows.ProcessTestWindow>();
services.AddTransient<Sharp.Demo.Views.Windows.LogDemoWindow>();
services.AddTransient<Sharp.Demo.Views.Windows.ConfigDemoWindow>();
services.AddTransient<Sharp.Demo.Views.Windows.WpfServicesWindow>();
// === 4. 构建容器 === // === 4. 构建容器 ===
_serviceProvider = services.BuildServiceProvider(); _serviceProvider = services.BuildServiceProvider();
@@ -256,17 +256,19 @@ namespace Sharp.Demo.ViewModels
_windowManager.ShowWindow<Sharp.Demo.Views.Windows.ProcessTestWindow>(moduleKey); _windowManager.ShowWindow<Sharp.Demo.Views.Windows.ProcessTestWindow>(moduleKey);
break; break;
// 其他窗口待实现
case "LogDemo": case "LogDemo":
_logger.LogInformation("正在打开日志管理窗口...");
_windowManager.ShowWindow<Sharp.Demo.Views.Windows.LogDemoWindow>(moduleKey);
break;
case "ConfigDemo": case "ConfigDemo":
_logger.LogInformation("正在打开配置管理窗口...");
_windowManager.ShowWindow<Sharp.Demo.Views.Windows.ConfigDemoWindow>(moduleKey);
break;
case "WpfServices": case "WpfServices":
_logger.LogWarning("模块 {ModuleKey} 窗口尚未实现", moduleKey); _logger.LogInformation("正在打开 WPF 服务窗口...");
System.Windows.MessageBox.Show( _windowManager.ShowWindow<Sharp.Demo.Views.Windows.WpfServicesWindow>(moduleKey);
$"{moduleKey} 窗口开发中...\n\n请按照 HttpServerWindow 的模板创建对应的窗口。",
"提示",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information
);
break; break;
default: default:
@@ -1,69 +1,168 @@
using System;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using Sharp.Wpf.Mvvm; using Sharp.Wpf.Mvvm;
using Sharp.Wpf.Commands; using Sharp.Wpf.Commands;
namespace Sharp.Demo.ViewModels.Pages namespace Sharp.Demo.ViewModels.Pages
{ {
/// <summary> /// <summary>
/// 配置管理演示 ViewModel /// 配置管理演示 ViewModel - 交互式演示配置读取和热重载
/// </summary> /// </summary>
public class ConfigDemoViewModel : ViewModelBase public class ConfigDemoViewModel : ViewModelBase
{ {
private string _configFile = "appsettings.json"; private readonly IConfiguration _configuration;
private bool _isHotReloadEnabled = true; private string _currentConfig = "正在加载配置...";
private string _configKey = "Logging:LogLevel:Default";
private string _configValue = "";
private string _configPreview = "等待加载配置...";
public string ConfigFile public ConfigDemoViewModel(IConfiguration configuration)
{ {
get => _configFile; _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
set => SetProperty(ref _configFile, value);
RefreshConfigCommand = new RelayCommand(RefreshConfig);
ShowSystemConfigCommand = new RelayCommand(ShowSystemConfig);
ShowLogConfigCommand = new RelayCommand(ShowLogConfig);
ShowNetworkConfigCommand = new RelayCommand(ShowNetworkConfig);
// 初始化时显示所有配置
RefreshConfig();
} }
public bool IsHotReloadEnabled #region 属性
public string CurrentConfig
{ {
get => _isHotReloadEnabled; get => _currentConfig;
set => SetProperty(ref _isHotReloadEnabled, value); set => SetProperty(ref _currentConfig, value);
} }
public string ConfigKey #endregion
#region 命令
public RelayCommand RefreshConfigCommand { get; }
public RelayCommand ShowSystemConfigCommand { get; }
public RelayCommand ShowLogConfigCommand { get; }
public RelayCommand ShowNetworkConfigCommand { get; }
#endregion
#region 命令实现
private void RefreshConfig()
{ {
get => _configKey; var sb = new StringBuilder();
set => SetProperty(ref _configKey, value); sb.AppendLine("📋 当前应用配置(完整)");
sb.AppendLine("".PadRight(50, '='));
sb.AppendLine();
// 递归显示所有配置
DisplayConfiguration(_configuration.GetChildren(), sb, 0);
sb.AppendLine();
sb.AppendLine("💡 提示:修改 appsettings.json 文件后会自动热重载");
CurrentConfig = sb.ToString();
} }
public string ConfigValue private void ShowSystemConfig()
{ {
get => _configValue; var sb = new StringBuilder();
set => SetProperty(ref _configValue, value); sb.AppendLine("⚙️ 系统配置 (System)");
sb.AppendLine("".PadRight(50, '='));
sb.AppendLine();
var appName = _configuration["System:AppName"];
var version = _configuration["System:Version"];
var httpIp = _configuration["System:HTTPIp"];
var httpPort = _configuration["System:HttpPort"];
sb.AppendLine($"应用名称: {appName ?? "未设置"}");
sb.AppendLine($"版本号: {version ?? "未设置"}");
sb.AppendLine($"HTTP IP: {httpIp ?? "未设置"}");
sb.AppendLine($"HTTP 端口: {httpPort ?? "未设置"}");
CurrentConfig = sb.ToString();
} }
public string ConfigPreview private void ShowLogConfig()
{ {
get => _configPreview; var sb = new StringBuilder();
set => SetProperty(ref _configPreview, value); sb.AppendLine("📝 日志配置 (SharpLog)");
sb.AppendLine("".PadRight(50, '='));
sb.AppendLine();
var useSerilog = _configuration["SharpLog:UseSerilog"];
var useConsole = _configuration["SharpLog:UseConsole"];
var minLevel = _configuration["SharpLog:MinLevel"];
var fileEnabled = _configuration["SharpLog:File:Enabled"];
var filePath = _configuration["SharpLog:File:Path"];
sb.AppendLine($"使用 Serilog: {useSerilog ?? "未设置"}");
sb.AppendLine($"控制台输出: {useConsole ?? "未设置"}");
sb.AppendLine($"最小日志级别: {minLevel ?? "未设置"}");
sb.AppendLine($"文件日志启用: {fileEnabled ?? "未设置"}");
sb.AppendLine($"日志文件路径: {filePath ?? "未设置"}");
CurrentConfig = sb.ToString();
} }
// 命令 private void ShowNetworkConfig()
public RelayCommand ReadConfigCommand { get; }
public RelayCommand ViewAllConfigCommand { get; }
public RelayCommand ReadDbConfigCommand { get; }
public RelayCommand ReadLogConfigCommand { get; }
public RelayCommand ReadServerConfigCommand { get; }
public RelayCommand TestHotReloadCommand { get; }
public RelayCommand OpenConfigFileCommand { get; }
public RelayCommand ValidateConfigCommand { get; }
public ConfigDemoViewModel()
{ {
ReadConfigCommand = new RelayCommand(() => ConfigValue = "读取配置功能待实现..."); var sb = new StringBuilder();
ViewAllConfigCommand = new RelayCommand(() => ConfigPreview = "查看所有配置功能待实现..."); sb.AppendLine("🌐 网络配置 (Server + NetServer + NetClient)");
ReadDbConfigCommand = new RelayCommand(() => ConfigPreview = "数据库配置:\n- ConnectionString\n- Provider\n功能待实现..."); sb.AppendLine("".PadRight(50, '='));
ReadLogConfigCommand = new RelayCommand(() => ConfigPreview = "日志配置:\n- MinimumLevel\n- WriteTo\n功能待实现..."); sb.AppendLine();
ReadServerConfigCommand = new RelayCommand(() => ConfigPreview = "服务器配置:\n- Port\n- Host\n功能待实现...");
TestHotReloadCommand = new RelayCommand(() => ConfigPreview = "热重载测试功能待实现...\n请修改 appsettings.json 文件测试"); sb.AppendLine("【服务器配置】");
OpenConfigFileCommand = new RelayCommand(() => ConfigPreview = "打开配置文件功能待实现..."); var serverHost = _configuration["Server:Host"];
ValidateConfigCommand = new RelayCommand(() => ConfigPreview = "配置验证功能待实现..."); var serverPort = _configuration["Server:Port"];
sb.AppendLine($" Host: {serverHost ?? "未设置"}");
sb.AppendLine($" Port: {serverPort ?? "未设置"}");
sb.AppendLine();
sb.AppendLine("【NetServer 中间件】");
var useLogging = _configuration["NetServer:UseLogging"];
var useException = _configuration["NetServer:UseExceptionHandling"];
var useCors = _configuration["NetServer:UseCors"];
sb.AppendLine($" 日志: {useLogging ?? "未设置"}");
sb.AppendLine($" 异常处理: {useException ?? "未设置"}");
sb.AppendLine($" CORS: {useCors ?? "未设置"}");
sb.AppendLine();
sb.AppendLine("【NetClient 配置】");
var timeout = _configuration["NetClient:Timeout"];
var retryEnabled = _configuration["NetClient:Retry:Enabled"];
var maxRetry = _configuration["NetClient:Retry:MaxRetryAttempts"];
sb.AppendLine($" 超时时间: {timeout ?? "未设置"}");
sb.AppendLine($" 重试启用: {retryEnabled ?? "未设置"}");
sb.AppendLine($" 最大重试次数: {maxRetry ?? "未设置"}");
CurrentConfig = sb.ToString();
} }
#endregion
#region 辅助方法
private void DisplayConfiguration(IEnumerable<IConfigurationSection> sections, StringBuilder sb, int level)
{
foreach (var section in sections)
{
var indent = new string(' ', level * 2);
if (section.Value != null)
{
sb.AppendLine($"{indent}{section.Key}: {section.Value}");
}
else
{
sb.AppendLine($"{indent}{section.Key}:");
DisplayConfiguration(section.GetChildren(), sb, level + 1);
}
}
}
#endregion
} }
} }
@@ -1,75 +1,98 @@
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Microsoft.Extensions.Logging;
using Sharp.Wpf.Mvvm; using Sharp.Wpf.Mvvm;
using Sharp.Wpf.Commands; using Sharp.Wpf.Commands;
namespace Sharp.Demo.ViewModels.Pages namespace Sharp.Demo.ViewModels.Pages
{ {
/// <summary> /// <summary>
/// 日志管理演示 ViewModel /// 日志管理演示 ViewModel - 交互式演示 Serilog 日志功能
/// </summary> /// </summary>
public class LogDemoViewModel : ViewModelBase public class LogDemoViewModel : ViewModelBase
{ {
private string _selectedLogLevel = "Information"; private readonly ILogger<LogDemoViewModel> _logger;
private string _logPreview = "日志预览区域...\n等待日志输出..."; private string _logOutput = "📝 日志管理演示已加载\n\n点击按钮测试不同级别的日志输出...\n";
public string SelectedLogLevel public LogDemoViewModel(ILogger<LogDemoViewModel> logger)
{ {
get => _selectedLogLevel; _logger = logger ?? throw new ArgumentNullException(nameof(logger));
set => SetProperty(ref _selectedLogLevel, value);
// 日志级别测试命令
LogTraceCommand = new RelayCommand(() =>
{
_logger.LogTrace("这是一条 Trace 级别的日志");
AppendLog("✅ Trace 日志已写入(通常不会显示,除非设置为 Trace 级别)");
});
LogDebugCommand = new RelayCommand(() =>
{
_logger.LogDebug("这是一条 Debug 级别的日志,包含调试信息:{DebugValue}", "DEBUG_DATA");
AppendLog("✅ Debug 日志已写入");
});
LogInfoCommand = new RelayCommand(() =>
{
_logger.LogInformation("用户触发了 Information 日志,时间:{Time}", DateTime.Now);
AppendLog("✅ Information 日志已写入");
});
LogWarningCommand = new RelayCommand(() =>
{
_logger.LogWarning("⚠️ 这是一条警告日志,磁盘空间不足:{FreeSpace}GB", 5.2);
AppendLog("⚠️ Warning 日志已写入");
});
LogErrorCommand = new RelayCommand(() =>
{
_logger.LogError("❌ 发生了一个错误:连接数据库失败");
AppendLog("❌ Error 日志已写入");
});
LogFatalCommand = new RelayCommand(() =>
{
_logger.LogCritical("💥 严重错误:系统核心组件崩溃");
AppendLog("💥 Critical (Fatal) 日志已写入");
});
ClearLogCommand = new RelayCommand(() =>
{
LogOutput = "📝 日志已清空\n\n";
});
AppendLog("💡 日志文件位置: logs/demo-{Date}.log");
AppendLog("💡 日志级别已在 appsettings.json 中配置");
} }
public string LogPreview #region 属性
public string LogOutput
{ {
get => _logPreview; get => _logOutput;
set => SetProperty(ref _logPreview, value); set => SetProperty(ref _logOutput, value);
} }
public ObservableCollection<string> LogLevels { get; } = new() #endregion
{
"Trace", "Debug", "Information", "Warning", "Error", "Critical" #region 命令
};
// 日志级别测试命令
public RelayCommand LogTraceCommand { get; } public RelayCommand LogTraceCommand { get; }
public RelayCommand LogDebugCommand { get; } public RelayCommand LogDebugCommand { get; }
public RelayCommand LogInformationCommand { get; } public RelayCommand LogInfoCommand { get; }
public RelayCommand LogWarningCommand { get; } public RelayCommand LogWarningCommand { get; }
public RelayCommand LogErrorCommand { get; } public RelayCommand LogErrorCommand { get; }
public RelayCommand LogCriticalCommand { get; } public RelayCommand LogFatalCommand { get; }
public RelayCommand ClearLogCommand { get; }
// 结构化日志命令 #endregion
public RelayCommand LogWithParamsCommand { get; }
public RelayCommand LogWithExceptionCommand { get; }
public RelayCommand LogPerformanceCommand { get; }
public RelayCommand LogBusinessCommand { get; }
// 日志操作命令 #region 辅助方法
public RelayCommand OpenLogFolderCommand { get; }
public RelayCommand ViewLatestLogCommand { get; }
public RelayCommand ClearLogsCommand { get; }
public LogDemoViewModel()
{
LogTraceCommand = new RelayCommand(() => AppendLog("[Trace] 追踪级别日志 - 功能待实现"));
LogDebugCommand = new RelayCommand(() => AppendLog("[Debug] 调试级别日志 - 功能待实现"));
LogInformationCommand = new RelayCommand(() => AppendLog("[Information] 信息级别日志 - 功能待实现"));
LogWarningCommand = new RelayCommand(() => AppendLog("[Warning] 警告级别日志 - 功能待实现"));
LogErrorCommand = new RelayCommand(() => AppendLog("[Error] 错误级别日志 - 功能待实现"));
LogCriticalCommand = new RelayCommand(() => AppendLog("[Critical] 严重错误日志 - 功能待实现"));
LogWithParamsCommand = new RelayCommand(() => AppendLog("带参数日志功能待实现..."));
LogWithExceptionCommand = new RelayCommand(() => AppendLog("带异常日志功能待实现..."));
LogPerformanceCommand = new RelayCommand(() => AppendLog("性能日志功能待实现..."));
LogBusinessCommand = new RelayCommand(() => AppendLog("业务日志功能待实现..."));
OpenLogFolderCommand = new RelayCommand(() => AppendLog("打开日志文件夹功能待实现..."));
ViewLatestLogCommand = new RelayCommand(() => AppendLog("查看最新日志功能待实现..."));
ClearLogsCommand = new RelayCommand(() => LogPreview = "");
}
private void AppendLog(string message) private void AppendLog(string message)
{ {
LogPreview += $"\n[{DateTime.Now:HH:mm:ss}] {message}"; LogOutput += $"[{DateTime.Now:HH:mm:ss}] {message}\n";
} }
#endregion
} }
} }
@@ -0,0 +1,91 @@
<Window x:Class="Sharp.Demo.Views.Windows.ConfigDemoWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
Title="配置管理演示"
Height="600"
Width="900"
WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 标题 -->
<TextBlock Grid.Row="0"
Text="⚙️ 配置管理演示"
FontSize="24"
FontWeight="Bold"
Margin="0,0,0,20"/>
<!-- 内容区 -->
<ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBlock Text="Sharp.Config 模块演示"
FontSize="18"
FontWeight="Bold"
Margin="0,0,0,10"/>
<TextBlock TextWrapping="Wrap"
Margin="0,0,0,20">
这里演示 Sharp.Config 模块的功能,包括:
• 多格式支持(JSON/XML/INI/TOML)
• 热重载(文件变化自动更新)
• 环境变量覆盖
• 强类型配置(IOptions 模式)
• 配置验证(DataAnnotations)
</TextBlock>
<!-- 当前配置 -->
<GroupBox Header="当前配置" Margin="0,0,0,20">
<TextBox Text="{Binding CurrentConfig, Mode=OneWay}"
Height="250"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
TextWrapping="Wrap"
FontFamily="Consolas"
Margin="10"/>
</GroupBox>
<!-- 操作 -->
<GroupBox Header="配置操作">
<StackPanel Margin="10">
<Button Content="刷新配置"
Command="{Binding RefreshConfigCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="查看系统配置"
Command="{Binding ShowSystemConfigCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="查看日志配置"
Command="{Binding ShowLogConfigCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="查看网络配置"
Command="{Binding ShowNetworkConfigCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
<!-- 底部按钮 -->
<StackPanel Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,20,0,0">
<Button Content="关闭"
Click="CloseButton_Click"
Width="100"/>
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,20 @@
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Sharp.Demo.ViewModels.Pages;
namespace Sharp.Demo.Views.Windows
{
public partial class ConfigDemoWindow : Window
{
public ConfigDemoWindow(IServiceProvider serviceProvider)
{
InitializeComponent();
DataContext = serviceProvider.GetRequiredService<ConfigDemoViewModel>();
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}
@@ -0,0 +1,105 @@
<Window x:Class="Sharp.Demo.Views.Windows.LogDemoWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
Title="日志管理演示"
Height="600"
Width="900"
WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 标题 -->
<TextBlock Grid.Row="0"
Text="📝 日志管理演示"
FontSize="24"
FontWeight="Bold"
Margin="0,0,0,20"/>
<!-- 内容区 -->
<ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBlock Text="Sharp.Log 模块演示"
FontSize="18"
FontWeight="Bold"
Margin="0,0,0,10"/>
<TextBlock TextWrapping="Wrap"
Margin="0,0,0,20">
这里演示 Sharp.Log 模块的功能,包括:
• Serilog 结构化日志
• 多级别日志(Trace/Debug/Info/Warning/Error/Fatal)
• 文件日志(滚动、保留策略)
• 控制台日志
• 日志富化(线程ID、进程ID、机器名等)
</TextBlock>
<!-- 日志级别演示 -->
<GroupBox Header="日志级别演示" Margin="0,0,0,20">
<StackPanel Margin="10">
<Button Content="Trace 日志"
Command="{Binding LogTraceCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="Debug 日志"
Command="{Binding LogDebugCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="Information 日志"
Command="{Binding LogInfoCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="Warning 日志"
Command="{Binding LogWarningCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="Error 日志"
Command="{Binding LogErrorCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
<Button Content="Fatal 日志"
Command="{Binding LogFatalCommand}"
Margin="0,5"
HorizontalAlignment="Left"
Width="150"/>
</StackPanel>
</GroupBox>
<!-- 日志输出 -->
<GroupBox Header="日志输出(实时)">
<TextBox Text="{Binding LogOutput, Mode=OneWay}"
Height="200"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
TextWrapping="Wrap"
FontFamily="Consolas"
Margin="10"/>
</GroupBox>
</StackPanel>
</ScrollViewer>
<!-- 底部按钮 -->
<StackPanel Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,20,0,0">
<Button Content="清空日志"
Command="{Binding ClearLogCommand}"
Width="100"
Margin="0,0,10,0"/>
<Button Content="关闭"
Click="CloseButton_Click"
Width="100"/>
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,20 @@
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Sharp.Demo.ViewModels.Pages;
namespace Sharp.Demo.Views.Windows
{
public partial class LogDemoWindow : Window
{
public LogDemoWindow(IServiceProvider serviceProvider)
{
InitializeComponent();
DataContext = serviceProvider.GetRequiredService<LogDemoViewModel>();
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}
@@ -0,0 +1,169 @@
<Window x:Class="Sharp.Demo.Views.Windows.WpfServicesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
Title="WPF 服务演示"
Height="700"
Width="1000"
WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 标题 -->
<TextBlock Grid.Row="0"
Text="🎨 WPF 服务演示"
FontSize="24"
FontWeight="Bold"
Margin="0,0,0,20"/>
<!-- 内容区 -->
<ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<!-- 左侧:功能按钮 -->
<ScrollViewer Grid.Column="0"
VerticalScrollBarVisibility="Auto"
Margin="0,0,10,0">
<StackPanel>
<!-- 对话框服务 -->
<GroupBox Header="📢 对话框服务" Margin="0,0,0,15">
<StackPanel Margin="10">
<Button Content="信息对话框"
Command="{Binding ShowMessageCommand}"
Margin="0,5"/>
<Button Content="确认对话框"
Command="{Binding ShowConfirmCommand}"
Margin="0,5"/>
<Button Content="警告对话框"
Command="{Binding ShowWarningCommand}"
Margin="0,5"/>
<Button Content="错误对话框"
Command="{Binding ShowErrorCommand}"
Margin="0,5"/>
</StackPanel>
</GroupBox>
<!-- 文件对话框 -->
<GroupBox Header="📁 文件对话框" Margin="0,0,0,15">
<StackPanel Margin="10">
<Button Content="打开文件"
Command="{Binding OpenFileCommand}"
Margin="0,5"/>
<Button Content="保存文件"
Command="{Binding SaveFileCommand}"
Margin="0,5"/>
<Button Content="选择文件夹"
Command="{Binding SelectFolderCommand}"
Margin="0,5"/>
<Button Content="多选文件"
Command="{Binding OpenMultipleFilesCommand}"
Margin="0,5"/>
</StackPanel>
</GroupBox>
<!-- UI 线程调度 -->
<GroupBox Header="🔄 UI 线程调度" Margin="0,0,0,15">
<StackPanel Margin="10">
<Button Content="UI 线程调用"
Command="{Binding InvokeOnUIThreadCommand}"
Margin="0,5"/>
<Button Content="异步 UI 调用"
Command="{Binding InvokeAsyncCommand}"
Margin="0,5"/>
<Button Content="后台任务(3秒)"
Command="{Binding BackgroundTaskCommand}"
Margin="0,5"/>
</StackPanel>
</GroupBox>
<!-- MVVM 基础 -->
<GroupBox Header="🎯 MVVM 基础" Margin="0,0,0,15">
<StackPanel Margin="10">
<Button Content="触发属性变更"
Command="{Binding TriggerPropertyChangeCommand}"
Margin="0,5"/>
<Button Content="同步命令"
Command="{Binding SyncCommandDemo}"
Margin="0,5"/>
<Button Content="异步命令"
Command="{Binding AsyncCommandDemo}"
Margin="0,5"/>
<Button Content="带参数命令"
Command="{Binding CommandWithParamDemo}"
CommandParameter="测试参数"
Margin="0,5"/>
</StackPanel>
</GroupBox>
<!-- 应用状态管理 -->
<GroupBox Header="📊 应用状态管理" Margin="0,0,0,15">
<StackPanel Margin="10">
<TextBlock Text="主题:" Margin="0,5,0,0"/>
<ComboBox SelectedItem="{Binding SelectedTheme}" Margin="0,5">
<ComboBoxItem Content="Light"/>
<ComboBoxItem Content="Dark"/>
<ComboBoxItem Content="Auto"/>
</ComboBox>
<TextBlock Text="语言:" Margin="0,10,0,0"/>
<ComboBox SelectedItem="{Binding SelectedLanguage}" Margin="0,5">
<ComboBoxItem Content="zh-CN"/>
<ComboBoxItem Content="en-US"/>
</ComboBox>
<TextBlock Text="用户名:" Margin="0,10,0,0"/>
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}"
Margin="0,5"/>
<CheckBox Content="调试模式"
IsChecked="{Binding IsDebugMode}"
Margin="0,10,0,5"/>
<Button Content="刷新状态摘要"
Command="{Binding RefreshStateSummaryCommand}"
Margin="0,10,0,5"/>
<Button Content="重置状态"
Command="{Binding ResetAppStateCommand}"
Margin="0,5"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
<!-- 右侧:日志输出 -->
<GroupBox Grid.Column="1"
Header="📝 日志输出">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"
Text="{Binding LogText, Mode=OneWay}"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
TextWrapping="Wrap"
FontFamily="Consolas"
FontSize="11"/>
<Button Grid.Row="1"
Content="清空日志"
Command="{Binding ClearLogCommand}"
HorizontalAlignment="Right"
Width="100"
Margin="0,10,0,0"/>
</Grid>
</GroupBox>
</Grid>
</ScrollViewer>
</Grid>
</Window>
@@ -0,0 +1,15 @@
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Sharp.Demo.ViewModels.Pages;
namespace Sharp.Demo.Views.Windows
{
public partial class WpfServicesWindow : Window
{
public WpfServicesWindow(IServiceProvider serviceProvider)
{
InitializeComponent();
DataContext = serviceProvider.GetRequiredService<WpfServicesViewModel>();
}
}
}