wpf 基于 JSON 的扩展配置 (Extended Config)” 功能

实现 "基于 JSON 的扩展配置 (Extended Config)" 功能的详细教程。我们将按照 Model (数据层) -> ViewModel (逻辑层) -> View (UI层) 的顺序进行。

这个功能的 核心思想 是:

  1. 数据库 存的是一个长字符串(JSON 格式)。
  2. 界面 显示的是一个表格(List 列表)。
  3. ViewModel 负责在"字符串"和"列表"之间来回转换。

第一步:修改数据库实体模型 (Model)

我们需要在数据库表中增加一列,用来专门存这些"乱七八糟"的扩展配置。

  1. 打开文件 : D:\BZW\MyQucikDevFrameWork\QuickNetFrameWork\QuickWpf\QuickWpf.Core\Models\Business\Recipe.cs

  2. 添加代码 :
    在 Recipe 类中,添加一个 ExtendedAttributes 字符串属性。

    // 在 Recipe 类内部添加:
    [SugarTable("Recipes")]
    public class Recipe
    {
    // ... 其他已有属性 ...

    复制代码
     /// <summary>
     /// 扩展属性 (JSON 格式),用于存储不固定的配方参数
     /// ColumnDataType = "TEXT" 告诉数据库这是一个长文本字段,
     能存很多内容
     /// </summary>
     [SugarColumn(ColumnDataType = "TEXT", IsNullable = 
     true)]
     public string ExtendedAttributes { get; set; } = "{}
     "; // 默认为空 JSON 对象

    }

第二步:创建列表项辅助类 (Helper Class)

界面上的表格(DataGrid)需要绑定到一个对象列表。我们需要定义这个"对象"长什么样(比如有 Key, Value, Description 三列)。

  1. 打开文件 : D:\BZW\MyQucikDevFrameWork\QuickNetFrameWork\QuickWpf\QuickWpf.Modules.Hardware\ViewModels\RecipeViewModel.cs (注:你也可以新建一个单独的 .cs 文件,但为了方便,我们先放在 ViewModel 文件里)

  2. 添加代码 :
    在 RecipeViewModel 类的 外面 (也就是 namespace 里面),定义 ExtendedAttributeItem 类。

    namespace QuickWpf.Modules.Hardware.ViewModels
    {
    // --- 新增这个类 ---
    public class ExtendedAttributeItem : BindableBase
    {
    private string _key = string.Empty;
    public string Key
    {
    get => _key;
    set => SetProperty(ref _key, value);
    }

    复制代码
         private string _value = string.Empty;
         public string Value 
         { 
             get => _value; 
             set => SetProperty(ref _value, value); 
         }
    
         private string _description = string.Empty;
         public string Description 
         { 
             get => _description; 
             set => SetProperty(ref _description, value); 
         }
     }
     // ------------------
    
     public class RecipeViewModel : BindableBase 
     {
         // ...
     }

    }

第三步:在 ViewModel 中编写逻辑 (核心步骤)

这是最关键的一步,我们要处理"加载时把 JSON 变列表"和"保存时把列表变 JSON"。

  1. 打开文件 : D:\BZW\MyQucikDevFrameWork\QuickNetFrameWork\QuickWpf\QuickWpf.Modules.Hardware\ViewModels\RecipeViewModel.cs

  2. 修改代码 :在 RecipeViewModel 类内部添加以下内容。

    2.1 定义列表属性和命令

    复制代码
    // 1. 定义绑定的数据源
    private ObservableCollection<ExtendedAttributeItem> 
    _extendedAttributesList;
    public ObservableCollection<ExtendedAttributeItem> 
    ExtendedAttributesList
    {
        get => _extendedAttributesList;
        set => SetProperty(ref _extendedAttributesList, 
        value);
    }
    
    // 2. 定义选中项(用于删除功能)
    private ExtendedAttributeItem? 
    _selectedExtendedAttribute;
    public ExtendedAttributeItem? SelectedExtendedAttribute
    {
        get => _selectedExtendedAttribute;
        set => SetProperty(ref _selectedExtendedAttribute, 
        value);
    }
    
    // 3. 定义按钮命令
    public DelegateCommand AddExtendedAttributeCommand { 
    get; }
    public DelegateCommand RemoveExtendedAttributeCommand { 
    get; }

    2.2 在构造函数中初始化命令

    复制代码
    public RecipeViewModel(...)
    {
        // ... 其他初始化 ...
        
        // 初始化命令
        AddExtendedAttributeCommand = new DelegateCommand
        (OnAddExtendedAttribute);
        RemoveExtendedAttributeCommand = new DelegateCommand
        (OnRemoveExtendedAttribute);
    }

    2.3 实现加载逻辑 (JSON -> List) 找到 LoadRecipeDetails 方法(或者你加载配方详情的地方),添加转换逻辑:

    复制代码
    private void LoadRecipeDetails()
    {
        // ... 加载其他属性 ...
    
        // --- 新增:加载扩展属性 ---
        try
        {
            if (string.IsNullOrWhiteSpace(SelectedRecipe.
            ExtendedAttributes) || SelectedRecipe.
            ExtendedAttributes == "{}")
            {
                // 如果是空的,就创建一个新列表
                ExtendedAttributesList = new 
                ObservableCollection<ExtendedAttributeItem>
                ();
            }
            else
            {
                // 使用 System.Text.Json 将字符串反序列化为对象
                列表
                var list = System.Text.Json.JsonSerializer.
                Deserialize<List<ExtendedAttributeItem>>
                (SelectedRecipe.ExtendedAttributes);
                ExtendedAttributesList = new 
                ObservableCollection<ExtendedAttributeItem>
                (list);
            }
        }
        catch
        {
            // 如果解析失败(比如格式坏了),就重置为空列表,防止报
            错
            ExtendedAttributesList = new 
            ObservableCollection<ExtendedAttributeItem>();
        }
    }

    2.4 实现保存逻辑 (List -> JSON) 找到 OnSave 方法,添加转换逻辑:

    复制代码
    private void OnSave()
    {
        if (SelectedRecipe != null)
        {
            // --- 新增:保存扩展属性 ---
            if (ExtendedAttributesList != null)
            {
                // 将对象列表序列化为 JSON 字符串,存回 Recipe 实
                体
                SelectedRecipe.ExtendedAttributes = System.
                Text.Json.JsonSerializer.Serialize
                (ExtendedAttributesList);
            }
            
            // ... 执行数据库保存 ...
            _databaseService.Db.Storageable(SelectedRecipe).
            ExecuteCommand();
        }
    }

    2.5 实现增删行逻辑

    复制代码
    private void OnAddExtendedAttribute()
    {
        if (ExtendedAttributesList == null) 
            ExtendedAttributesList = new 
            ObservableCollection<ExtendedAttributeItem>();
            
        // 添加一行默认数据
        ExtendedAttributesList.Add(new ExtendedAttributeItem 
        { Key = "New Key", Value = "", Description = "" });
    }
    
    private void OnRemoveExtendedAttribute()
    {
        if (SelectedExtendedAttribute != null)
        {
            ExtendedAttributesList.Remove
            (SelectedExtendedAttribute);
        }
    }

第四步:在 XAML 中添加界面 (View)

最后,我们需要在界面上画出这个表格。

  1. 打开文件 : D:\BZW\MyQucikDevFrameWork\QuickNetFrameWork\QuickWpf\QuickWpf.Modules.Hardware\Views\RecipePage.xaml

  2. 添加代码 :
    找到 TabControl 部分,添加一个新的 TabItem 。

    <TabItem Header="Extended Config">
    <Grid Margin="0,8,0,0">
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    复制代码
         <!-- 1. 顶部工具栏:添加/删除按钮 -->
         <!-- Visibility 绑定:只有在编辑模式(IsEditing=True)下
         才显示 -->
         <StackPanel Orientation="Horizontal" Margin="0,0,0,
         8" 
                     Visibility="{Binding IsEditing, 
                     Converter={StaticResource 
                     BoolToVisConverter}}">
             
             <Button Command="{Binding 
             AddExtendedAttributeCommand}" 
                     Content="Add Attribute" 
                     Style="{DynamicResource MahApps.Styles.
                     Button.Square.Accent}" 
                     Margin="0,0,8,0"/>
                     
             <Button Command="{Binding 
             RemoveExtendedAttributeCommand}" 
                     Content="Remove" 
                     Style="{DynamicResource MahApps.Styles.
                     Button.Square}"/>
         </StackPanel>
    
         <!-- 2. 数据表格 -->
         <DataGrid Grid.Row="1" 
                   ItemsSource="{Binding 
                   ExtendedAttributesList}" 
                   SelectedItem="{Binding 
                   SelectedExtendedAttribute}" 
                   AutoGenerateColumns="False" 
                   CanUserAddRows="False"
                   IsReadOnly="{Binding IsEditing, 
                   Converter={StaticResource 
                   InvertBooleanConverter}}">
                   <!-- IsReadOnly: 如果不是编辑模式,表格就只
                   读 -->
    
             <DataGrid.Columns>
                 <!-- Key 列 -->
                 <DataGridTextColumn Binding="{Binding Key}
                 " Header="Key" Width="150"/>
                 <!-- Value 列 -->
                 <DataGridTextColumn Binding="{Binding 
                 Value}" Header="Value" Width="*"/>
                 <!-- Description 列 -->
                 <DataGridTextColumn Binding="{Binding 
                 Description}" Header="Description" 
                 Width="*"/>
             </DataGrid.Columns>
         </DataGrid>
     </Grid>
    </TabItem>

总结

做完这四步,流程就通了:

  1. 用户 点击"Edit" -> 点击"Add Attribute" -> 表格里多了一行 -> 输入 Key="Speed", Value="100" 。
  2. ViewModel 里的 ExtendedAttributesList 多了一个对象。
  3. 用户 点击"Save"。
  4. ViewModel 把 List 变成字符串 [{"Key":"Speed","Value":"100",...}] 。
  5. Model 把这个字符串存进数据库的 ExtendedAttributes 字段。
  6. 下次 加载 时,反过来把字符串变回 List 显示在表格上。
相关推荐
Leon-Ning Liu3 小时前
19c RAC 环境 Patch 38326922 应用实战
数据库·oracle
a587695 小时前
Oracle数据库体系结构深度解析:从内核到应用的理论全景
数据库·oracle
智航GIS6 小时前
9.6 JSON 基本操作
python·json
低调小一9 小时前
Google A2UI 入门:让 Agent “说 UI”,用声明式 JSON 安全渲染到原生界面
人工智能·安全·ui·json
dishugj9 小时前
【Oracle】Oracle数据库迁移-数据文件(非系统数据文件)目录迁移
数据库·oracle
Leon-Ning Liu9 小时前
SYSAUX表空间使用率暴增处理方式
数据库·oracle
gAlAxy...9 小时前
MyBatis 缓存深度解析(一级 / 二级缓存原理 + 实战 + 避坑)
wpf
DBA小马哥12 小时前
达梦VS金仓:Oracle国产替代深度对比
数据库·oracle·kingbasees·金仓数据库
manuel_8975712 小时前
三 数据库系统
数据库·oracle
剑来.13 小时前
数据库慢的时候,我最先看哪 5 个地方
数据库·oracle