1 refactor(config): 将AppSettings移至Application层并更新配置结构

2
    3 - 将AppSettings从DMS.Infrastructure移至DMS.Application
    4 - 将DatabaseSettings重命名为AppSettings.Database并更新所有引用
    5 - 将配置文件从appSettings.json更改为dms_config.json
    6 - 更新所有项目引用以使用新的AppSettings命名空间
    7 - 移除DI容器中的SqlSugarDbContext直接实例化
    8 - 添加Material Design Icons字体并更新设置视图UI
    9 - 通过移除不必要的变量映射更新来优化S7服务
   10 - 将数据库连接字符串属性名从Database更新为DbName
This commit is contained in:
2025-10-04 18:42:12 +08:00
parent abcaf3e160
commit ec1f94a898
14 changed files with 152 additions and 222 deletions

View File

@@ -1,46 +1,46 @@
using AutoMapper;
using DMS.Core.Models;
using Newtonsoft.Json;
namespace DMS.Application.Configurations
{
public class DatabaseSettings
{
public string DbType { get; set; } = "MySql";
public string Server { get; set; } = "127.0.0.1";
public int Port { get; set; } = 3306;
public string UserId { get; set; } = "root";
public string Password { get; set; } = "Pgw15221236646";
public string Database { get; set; } = "pmswpf";
}
public class AppSettings
{
private readonly IMapper _mapper;
public class Database
{
public string DbType { get; set; } = "MySql";
public string Server { get; set; } = "127.0.0.1";
public int Port { get; set; } = 3306;
public string UserId { get; set; } = "root";
public string Password { get; set; } = "Pgw15221236646";
public string DbName { get; set; } = "dms_test";
}
public DatabaseSettings Database { get; set; } = new DatabaseSettings();
public Database Db { get; set; } = new Database();
public string Theme { get; set; } = "跟随系统";
public bool EnableS7Service { get; set; } = true;
public bool EnableMqttService { get; set; } = true;
public bool EnableOpcUaService { get; set; } = true;
public bool MinimizeToTrayOnClose { get; set; } = true;
public List<MenuBean> Menus { get; set; } = new List<MenuBean>();
public int DefaultPollingInterval { get; set; } = 30000; // 默认轮询间隔30秒
private static readonly string SettingsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appSettings.json");
private static readonly string SettingsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigJsonFileName);
private const string ConfigJsonFileName = "dms_config.json";
public AppSettings Load()
public AppSettings? Load()
{
if (File.Exists(SettingsFilePath))
{
string json = File.ReadAllText(SettingsFilePath);
AppSettings appSettings = JsonConvert.DeserializeObject<AppSettings>(json);
return appSettings;
AppSettings? appSettings = JsonConvert.DeserializeObject<AppSettings>(json);
return appSettings ?? throw new InvalidOperationException("加载配置文件出现了错误。");
}
return new AppSettings();
return null;
}
public void Save()
@@ -51,7 +51,7 @@ namespace DMS.Application.Configurations
public string ToConnectionString()
{
return $"server={Database.Server};port={Database.Port};user={Database.UserId};password={Database.Password};database={Database.Database};";
return $"server={Db.Server};port={Db.Port};user={Db.UserId};password={Db.Password};database={Db.DbName};";
}
}
}

View File

@@ -2,6 +2,7 @@
using AutoMapper;
using AutoMapper.Internal;
using DMS.Application.Configurations;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Application.Services;
@@ -11,7 +12,6 @@ using DMS.Core.Interfaces.Repositories;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Repositories;
using Microsoft.Extensions.DependencyInjection;
using DMS.Infrastructure.Configurations;
namespace DMS.Infrastructure.UnitTests.Services;
@@ -37,11 +37,7 @@ public class BaseServiceTest
});
// 2. 配置数据库上下文 (在测试中通常使用单例)
services.AddSingleton<SqlSugarDbContext>(_ =>
{
var appSettings = new AppSettings { Database = { Database = "dms_test" } };
return new SqlSugarDbContext(appSettings);
});
services.AddSingleton<SqlSugarDbContext>();
// --- 注册服务和仓储 ---
// 使用 Transient 或 Scoped 取决于服务的生命周期需求对于测试Transient 通常更安全。

View File

@@ -26,4 +26,8 @@
<ProjectReference Include="..\DMS.Core\DMS.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Configurations\" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
using DMS.Infrastructure.Configurations;
using DMS.Application.Configurations;
using SqlSugar;
namespace DMS.Infrastructure.Data;
@@ -16,7 +16,7 @@ public class SqlSugarDbContext
public SqlSugarClient GetInstance()
{
var connectionString = _settings.ToConnectionString();
var dbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), _settings.Database.DbType);
var dbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), _settings.Db.DbType);
return new SqlSugarClient(new ConnectionConfig
{

View File

@@ -1,7 +1,6 @@
using DMS.Core.Enums;
using DMS.Core.Interfaces.Repositories;
using DMS.Core.Models;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Entities;
using Microsoft.Extensions.Logging;

View File

@@ -426,18 +426,6 @@ namespace DMS.Infrastructure.Services.S7
// 如果变量的S7相关属性发生变化
switch (e.PropertyType)
{
case VariablePropertyType.S7Address:
// S7地址变化需要更新设备上下文中的变量映射
if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context))
{
// 先移除旧地址的变量
context.Variables.Remove(e.Variable.S7Address, out _);
// 添加新地址的变量
context.Variables.AddOrUpdate(e.Variable.S7Address, e.Variable, (key, oldValue) => e.Variable);
_logger.LogInformation("已更新设备 {DeviceId} 中变量 {VariableId} 的S7地址映射",
e.Variable.VariableTable.DeviceId, e.Variable.Id);
}
break;
case VariablePropertyType.IsActive:
// 变量激活状态变化,更新变量列表

View File

@@ -2,13 +2,13 @@
using AutoMapper;
using AutoMapper.Internal;
using DMS.Application.Configurations;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Application.Services;
using DMS.Application.Services.Database;
using DMS.Core.Interfaces;
using DMS.Core.Interfaces.Repositories;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Repositories;
using DMS.WPF.Interfaces;
@@ -40,11 +40,7 @@ public class BaseServiceTest
});
// 2. 配置数据库上下文 (在测试中通常使用单例)
services.AddSingleton<SqlSugarDbContext>(_ =>
{
var appSettings = new AppSettings { Database = { Database = "dms_test" } };
return new SqlSugarDbContext(appSettings);
});
services.AddSingleton<SqlSugarDbContext>();
// --- 注册服务和仓储 ---
// 使用 Transient 或 Scoped 取决于服务的生命周期需求对于测试Transient 通常更安全。

View File

@@ -34,6 +34,9 @@
<!-- System Accent Color as Brush -->
<SolidColorBrush x:Key="SystemAccentColorBrush" Color="{DynamicResource SystemAccentColor}" />
<!-- Material Design Icons Font -->
<FontFamily x:Key="MdFontIcons">/Assets/Fonts/materialdesignicons-webfont.ttf#Material Design Icons</FontFamily>
<!-- Enum Values for ComboBoxes -->
<ObjectDataProvider x:Key="ConditionTypeEnum" ObjectType="{x:Type sys:Enum}" MethodName="GetValues">
<ObjectDataProvider.MethodParameters>

View File

@@ -1,6 +1,7 @@
using System.Windows;
using AutoMapper;
using AutoMapper.Internal;
using DMS.Application.Configurations;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Application.Interfaces.Management;
@@ -15,7 +16,6 @@ using DMS.Core.Interfaces.Repositories;
using DMS.Core.Interfaces.Repositories.Triggers;
using DMS.Core.Interfaces.Services;
using DMS.Infrastructure.Configuration;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Interfaces;
using DMS.Infrastructure.Interfaces.Services;
@@ -174,6 +174,7 @@ public partial class App : System.Windows.Application
services.AddSingleton<ILoggerFactory, NLogLoggerFactory>();
services.AddSingleton<GrowlNotificationService>();
services.AddSingleton<INotificationService, NotificationService>();
// 注册核心服务
services.AddAutoMapper(cfg =>
@@ -218,11 +219,7 @@ public partial class App : System.Windows.Application
// 注册Core中的仓库
services.AddSingleton<AppSettings>();
services.AddSingleton<SqlSugarDbContext>(_ =>
{
var appSettings = new AppSettings { Database = { Database = "dms_test" } };
return new SqlSugarDbContext(appSettings);
});
services.AddSingleton<SqlSugarDbContext>();

View File

@@ -6,6 +6,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<EnableHotReload>true</EnableHotReload>
<ApplicationIcon>Assets\AppIcon2.ico</ApplicationIcon>
</PropertyGroup>
@@ -18,6 +19,9 @@
<ItemGroup>
<Resource Include="Assets\AppIcon.png" />
<Resource Include="Assets\AppIcon2.ico" />
<Resource Include="Assets\Fonts\materialdesignicons-webfont.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
@@ -169,21 +173,24 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DMS.Application\DMS.Application.csproj" />
<ProjectReference Include="..\DMS.Infrastructure\DMS.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="ViewModels\Items\" />
</ItemGroup>
<ItemGroup>
<None Update="Configurations\nlog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
</Project>

View File

@@ -3,7 +3,7 @@ using DMS.Application.DTOs;
using DMS.Core.Enums;
using System;
using System.Collections.Generic;
using DMS.Infrastructure.Configurations;
using DMS.Application.Configurations;
using Microsoft.Extensions.DependencyInjection;
namespace DMS.WPF.ViewModels.Items;

View File

@@ -1,5 +1,5 @@
using CommunityToolkit.Mvvm.Input;
using DMS.Infrastructure.Configurations;
using DMS.Application.Configurations;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;
@@ -39,12 +39,12 @@ public partial class SettingViewModel : ViewModelBase
public string SelectedDbType
{
get => _settings.Database.DbType;
get => _settings.Db.DbType;
set
{
if (_settings.Database.DbType != value)
if (_settings.Db.DbType != value)
{
_settings.Database.DbType = value;
_settings.Db.DbType = value;
OnPropertyChanged();
_settings.Save();
}
@@ -53,12 +53,12 @@ public partial class SettingViewModel : ViewModelBase
public string Server
{
get => _settings.Database.Server;
get => _settings.Db.Server;
set
{
if (_settings.Database.Server != value)
if (_settings.Db.Server != value)
{
_settings.Database.Server = value;
_settings.Db.Server = value;
OnPropertyChanged();
_settings.Save();
}
@@ -67,12 +67,12 @@ public partial class SettingViewModel : ViewModelBase
public int Port
{
get => _settings.Database.Port;
get => _settings.Db.Port;
set
{
if (_settings.Database.Port != value)
if (_settings.Db.Port != value)
{
_settings.Database.Port = value;
_settings.Db.Port = value;
OnPropertyChanged();
_settings.Save();
}
@@ -81,12 +81,12 @@ public partial class SettingViewModel : ViewModelBase
public string UserId
{
get => _settings.Database.UserId;
get => _settings.Db.UserId;
set
{
if (_settings.Database.UserId != value)
if (_settings.Db.UserId != value)
{
_settings.Database.UserId = value;
_settings.Db.UserId = value;
OnPropertyChanged();
_settings.Save();
}
@@ -95,26 +95,26 @@ public partial class SettingViewModel : ViewModelBase
public string Password
{
get => _settings.Database.Password;
get => _settings.Db.Password;
set
{
if (_settings.Database.Password != value)
if (_settings.Db.Password != value)
{
_settings.Database.Password = value;
_settings.Db.Password = value;
OnPropertyChanged();
_settings.Save();
}
}
}
public string Database
public string DbName
{
get => _settings.Database.Database;
get => _settings.Db.DbName;
set
{
if (_settings.Database.Database != value)
if (_settings.Db.DbName != value)
{
_settings.Database.Database = value;
_settings.Db.DbName = value;
OnPropertyChanged();
_settings.Save();
}
@@ -157,7 +157,7 @@ public partial class SettingViewModel : ViewModelBase
// 使用当前配置测试数据库连接
using var db = new SqlSugar.SqlSugarScope(new SqlSugar.ConnectionConfig()
{
DbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), _settings.Database.DbType),
DbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), _settings.Db.DbType),
ConnectionString = _settings.ToConnectionString(),
IsAutoCloseConnection = true
});

View File

@@ -7,8 +7,8 @@ using DMS.WPF.Services;
using System;
using System.Data;
using System.Threading.Tasks;
using DMS.Application.Configurations;
using DMS.Application.Services;
using DMS.Infrastructure.Configurations;
using DMS.WPF.Helper;
using DMS.WPF.Interfaces;
using DMS.WPF.Views;
@@ -32,8 +32,9 @@ public partial class SplashViewModel : ObservableObject
[ObservableProperty]
private string _loadingMessage = "正在加载...";
public SplashViewModel(ILogger<SplashViewModel> logger,IServiceProvider serviceProvider, IInitializeService initializeService,IDataEventService dataEventService,
IAppDataCenterService appDataCenterService,AppSettings appSettings)
public SplashViewModel(ILogger<SplashViewModel> logger, IServiceProvider serviceProvider,
IInitializeService initializeService, IDataEventService dataEventService,
IAppDataCenterService appDataCenterService, AppSettings appSettings)
{
_logger = logger;
_serviceProvider = serviceProvider;
@@ -50,13 +51,18 @@ public partial class SplashViewModel : ObservableObject
{
try
{
LoadingMessage = "正在加载系统配置...";
if (_appSettings.Load() == null)
{
//程序第一次启动
}
_logger.LogInformation("正在初始化数据库...");
LoadingMessage = "正在初始化数据库...";
_initializeService.InitializeTables();
_initializeService.InitializeMenus();
LoadingMessage = "正在加载系统配置...";
await _appDataCenterService.DataLoaderService.LoadAllDataToMemoryAsync();
// 可以在这里添加加载配置的逻辑
@@ -80,7 +86,7 @@ public partial class SplashViewModel : ObservableObject
{
// 处理初始化过程中的异常
LoadingMessage = $"初始化失败: {ex.Message}";
_logger.LogError(ex,$"初始化失败: {ex}");
_logger.LogError(ex, $"初始化失败: {ex}");
// 在此可以记录日志或显示错误对话框
return false;
}

View File

@@ -1,161 +1,95 @@
<UserControl x:Class="DMS.WPF.Views.SettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl
x:Class="DMS.WPF.Views.SettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<StackPanel>
<ui:SettingsExpander Header="通用设置"
Description="通用程序行为设置">
<ui:SettingsExpander Description="通用程序行为设置" Header="通用设置">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Glyph="&#xE713;" />
</ui:SettingsExpander.HeaderIcon>
<ui:SettingsExpander.Items>
<ui:SettingsCard Header="主题切换"
Description="切换应用程序的主题">
<ComboBox Width="120"
ItemsSource="{Binding Themes}"
SelectedItem="{Binding SelectedTheme, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ui:SettingsCard Description="切换应用程序的主题" Header="主题切换">
<ComboBox
Width="120"
ItemsSource="{Binding Themes}"
SelectedItem="{Binding SelectedTheme, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Header="点击关闭按钮时最小化到通知栏"
Description="开启后,点击主窗口的关闭按钮会将程序最小化到系统通知栏,而不是直接退出。"
IsClickEnabled="True">
<ui:SettingsCard
Description="开启后,点击主窗口的关闭按钮会将程序最小化到系统通知栏,而不是直接退出。"
Header="点击关闭按钮时最小化到通知栏"
IsClickEnabled="True">
<ui:ToggleSwitch IsOn="{Binding MinimizeToTrayOnClose, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Header="默认轮询间隔"
Description="设置变量的默认轮询间隔时间(毫秒)">
<TextBox Width="120"
Text="{Binding DefaultPollingInterval, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ui:SettingsCard Description="设置变量的默认轮询间隔时间(毫秒)" Header="默认轮询间隔">
<TextBox Width="120" Text="{Binding DefaultPollingInterval, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<ui:SettingsExpander x:Name="dbSettingCard"
Header="设置数据库"
Description="设置要连接的数据库,数据全部在数据库中存放">
<ui:SettingsExpander Description="设置要连接的数据库,数据全部在数据库中存放" Header="设置数据库">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.DataSense}"
VerticalAlignment="Center"
Margin="0,0,8,0"
FontSize="14" />
<ui:FontIcon
FontFamily="{StaticResource MdFontIcons}"
FontSize="18"
Glyph="&#xF01BC;" />
</ui:SettingsExpander.HeaderIcon>
<Button Content="测试连接"
Command="{Binding TestConnectionCommand}"
Style="{StaticResource AccentButtonStyle}"
Margin="0,10,0,0"
HorizontalAlignment="Left" />
<ui:SettingsExpander.Items>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="数据库类型:"
FontSize="14"
VerticalAlignment="Center"
Margin="30,0,10,0" />
<ComboBox Grid.Column="1"
MinWidth="200"
ItemsSource="{Binding AvailableDbTypes}"
SelectedItem="{Binding SelectedDbType}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="服务器地址:"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<TextBox Grid.Column="1"
Text="{Binding Server, UpdateSourceTrigger=PropertyChanged}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="服务器端口:"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<TextBox Grid.Column="1"
Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="用户名:"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<TextBox Grid.Column="1"
Text="{Binding UserId, UpdateSourceTrigger=PropertyChanged}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="密码:"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<TextBox Grid.Column="1"
Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard HorizontalAlignment="Left"
Width="{Binding ElementName=dbSettingCard ,Path=Width}">
<ikw:SimpleStackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="数据库名称:"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<TextBox Grid.Column="1"
Text="{Binding Database, UpdateSourceTrigger=PropertyChanged}" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<ui:SettingsExpander Header="SettingsExpander"
Description="The SettingsExpander has the same properties as a SettingsCard">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Glyph="&#xE91B;" />
</ui:SettingsExpander.HeaderIcon>
<Button Content="Content"
Style="{StaticResource AccentButtonStyle}" />
<Button
Margin="0,10,0,0"
HorizontalAlignment="Left"
Command="{Binding TestConnectionCommand}"
Content="测试连接"
Style="{StaticResource AccentButtonStyle}" />
<ui:SettingsExpander.Items>
<ui:SettingsCard Header="A basic SettingsCard within an SettingsExpander">
<Button Content="Button" />
<ui:SettingsCard Description="使用的数据库类型如Mysql,SqlServer等" Header="数据库类型">
<ComboBox
MinWidth="200"
ItemsSource="{Binding AvailableDbTypes}"
SelectedItem="{Binding SelectedDbType}" />
</ui:SettingsCard>
<ui:SettingsCard Description="SettingsCard within an Expander can be made clickable too!"
Header="This item can be clicked"
IsClickEnabled="True" />
<ui:SettingsCard ContentAlignment="Left">
<CheckBox
Content="Here the ContentAlignment is set to Left. This is great for e.g. CheckBoxes or RadioButtons" />
<ui:SettingsCard Description="数据库所在电脑的地址" Header="服务器地址">
<TextBox MinWidth="200" Text="{Binding Server, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Description="数据库服务器端口号" Header="服务器端口">
<TextBox MinWidth="200" Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Description="数据库登录用户名" Header="用户名">
<TextBox MinWidth="200" Text="{Binding UserId, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Description="数据库登录密码" Header="密码">
<TextBox MinWidth="200" Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
<ui:SettingsCard Description="要连接的数据库名称" Header="数据库名称">
<TextBox MinWidth="200" Text="{Binding DbName, UpdateSourceTrigger=PropertyChanged}" />
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<ui:SettingsExpander>
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.ScreenTime}" />
</ui:SettingsExpander.HeaderIcon>
</ui:SettingsExpander>
</StackPanel>
</UserControl>