You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用少量方法实现Edit按钮与Ok/Cancel按钮组的可见性切换

解决方案:复用编辑逻辑的子ViewModel模式

要实现7组独立的编辑按钮切换,同时只维护一套核心逻辑,最佳方式是创建一个封装编辑状态与命令的子ViewModel,让每组控件绑定到对应的子ViewModel实例。这样既避免重复代码,又保证每组状态独立。

1. 创建子ViewModel封装编辑逻辑

借助MVVM Community Toolkit的特性快速生成属性和命令,所有编辑相关的状态(可见性)和操作都在这里实现:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public partial class EditableFieldViewModel : ObservableObject
{
    // 核心状态:是否处于编辑模式
    [ObservableProperty]
    private bool _isEditing;

    // 保存原始值用于取消时回滚(可选)
    private string _originalValue;

    // 编辑按钮点击:进入编辑模式
    [RelayCommand]
    private void Edit()
    {
        IsEditing = true;
    }

    // OK按钮点击:退出编辑模式,可添加保存逻辑
    [RelayCommand]
    private void OkEdit()
    {
        // 此处可添加字段验证、保存到数据源等逻辑
        IsEditing = false;
    }

    // Cancel按钮点击:退出编辑模式,回滚原始值(可选)
    [RelayCommand]
    private void CancelEdit()
    {
        // 触发回滚事件,通知主ViewModel恢复原始值
        ValueRolledBack?.Invoke(this, _originalValue);
        IsEditing = false;
    }

    // 设置原始值的方法(供主ViewModel调用)
    public void SetOriginalValue(string value)
    {
        _originalValue = value;
    }

    // 回滚事件(主ViewModel订阅以恢复字段值)
    public event EventHandler<string> ValueRolledBack;

    // 适配原有XAML的可见性属性(也可通过转换器实现)
    public bool IsEditButtonVisible => !IsEditing;
    public bool IsOkCancelButtonVisible => IsEditing;
}

2. 主ViewModel中定义子VM实例

为7组字段各创建一个EditableFieldViewModel实例,同时维护业务字段:

using CommunityToolkit.Mvvm.ComponentModel;

public partial class MainViewModel : ObservableObject
{
    // 7组字段对应的子ViewModel实例
    public EditableFieldViewModel ControllerNameField { get; } = new();
    public EditableFieldViewModel DeviceIdField { get; } = new();
    public EditableFieldViewModel FirmwareVersionField { get; } = new();
    // ... 剩余4组同理

    // 业务字段示例:ControllerName
    [ObservableProperty]
    private string _controllerName = "Default Controller";

    public MainViewModel()
    {
        // 订阅回滚事件,Cancel时恢复原始值
        ControllerNameField.ValueRolledBack += (s, originalValue) =>
        {
            ControllerName = originalValue;
        };

        // 记录编辑前的原始值
        ControllerNameField.EditCommand.CanExecuteChanged += (s, e) =>
        {
            if (ControllerNameField.IsEditing)
            {
                ControllerNameField.SetOriginalValue(ControllerName);
            }
        };
    }
}

3. 修改XAML绑定到子ViewModel

将每组编辑控件的DataContext绑定到对应的子VM实例,复用同一套XAML结构:

<StackPanel
        Orientation="Horizontal"
        HorizontalAlignment="Center"
        Grid.Row="2"
        Grid.Column="0"
        Grid.ColumnSpan="4">
    <Label
        Style="{StaticResource DeviceInfoPropertyLabelStyle}">
        CONTROLLER NAME:
    </Label>
    <TextBox
        Text="{Binding ControllerName}"
        Style="{StaticResource DeviceInfoTextBoxStyle}" />
    <!-- 将编辑控件的DataContext设置为对应的子VM -->
    <Grid DataContext="{Binding ControllerNameField}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <StackPanel
            Orientation="Horizontal"
            Grid.Column="0">
            <Button
                Command="{Binding EditCommand}"
                Visibility="{Binding IsEditButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Collapsed}"
                Style="{StaticResource DeviceInfoEditButtonStyle}">
                Edit
            </Button>
        </StackPanel>
        <StackPanel
            Orientation="Horizontal"
            Grid.Column="0"
            Visibility="{Binding IsOkCancelButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Visible}">
            <Button
                Command="{Binding OkEditCommand}"
                Style="{StaticResource DeviceInfoEditOkButtonStyle}">
                OK
            </Button>
            <Button
                Command="{Binding CancelEditCommand}"
                Style="{StaticResource DeviceInfoEditCancelButtonStyle}">
                CANCEL
            </Button>
        </StackPanel>
    </Grid>
</StackPanel>

关键优势

  • 代码复用:仅需编写一套编辑逻辑,7组共用,无需为每组单独创建命令和属性
  • 状态独立:每组的编辑状态互不干扰,不会出现点击一个Edit所有组切换的问题
  • 扩展性强:后续新增字段组只需添加子VM实例和对应XAML,无需修改核心逻辑

内容的提问来源于stack exchange,提问作者Harlan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:01:16