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

点击EditingCellTemplate内按钮切换DataGrid的CellTemplate与EditingCellTemplate

解决DataGrid单元格模板切换的两种实用方案

你想要的效果是:双击权限单元格进入编辑模式(显示按钮列表),点击按钮更新权限后切回文本显示。我给你两种落地性强的方案,一种基于DataGrid自带的编辑机制,另一种用Behavior封装实现复用,按需选择:


方案一:利用DataGrid自带的CellEditingTemplate(简单直接)

你已经配置好了CellTemplate和CellEditingTemplate,默认双击单元格就会进入编辑状态,核心问题是点击按钮后如何退出编辑。我们可以通过ViewModel触发事件,让View响应并结束单元格编辑:

步骤1:在ViewModel中添加结束编辑的通知事件

public event EventHandler RequestEndEdit;

private void ExecuteUpdatePermissionCommand(PermissionLevel selectedPermission)
{
    // 先完成权限更新逻辑
    if (SelectedUsersModule != null)
    {
        SelectedUsersModule.PermissionLevel = selectedPermission;
    }
    
    // 触发结束编辑的通知
    RequestEndEdit?.Invoke(this, EventArgs.Empty);
}

步骤2:在View中订阅事件并处理编辑状态

给DataGrid添加Loaded事件,在后台代码中绑定ViewModel的事件:

private void PermissionDataGrid_Loaded(object sender, RoutedEventArgs e)
{
    if (sender is DataGrid dataGrid && dataGrid.DataContext is YourViewModel vm)
    {
        vm.RequestEndEdit += (s, args) =>
        {
            // 提交编辑,让单元格回到CellTemplate状态
            dataGrid.CommitEdit(DataGridEditingUnit.Cell, true);
            // 如果不需要保留编辑临时值,也可以用CancelEdit替代
            // dataGrid.CancelEdit(DataGridEditingUnit.Cell);
        };
    }
}

步骤3:在XAML中绑定Loaded事件

<DataGrid ItemsSource="{Binding AllUsersModules}" 
          SelectedItem="{Binding SelectedUsersModule}" 
          Style="{StaticResource BaseDataGridStyle}" 
          SelectionUnit="FullRow"
          Loaded="PermissionDataGrid_Loaded">
    <!-- 你的列配置保持不变 -->
</DataGrid>

这样点击按钮执行更新命令后,单元格就会自动切回显示模板了。


方案二:用Behavior封装(灵活可复用)

如果你想用Behavior封装这个逻辑,方便在其他DataGrid中复用,可以创建一个附加到DataGridCell的Behavior,手动控制编辑状态:

步骤1:创建PermissionCellEditBehavior

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

public class PermissionCellEditBehavior : Behavior<DataGridCell>
{
    // 定义绑定用的IsEditing依赖属性
    public static readonly DependencyProperty IsEditingProperty =
        DependencyProperty.Register(nameof(IsEditing), typeof(bool), typeof(PermissionCellEditBehavior),
            new PropertyMetadata(false, OnIsEditingChanged));

    public bool IsEditing
    {
        get => (bool)GetValue(IsEditingProperty);
        set => SetValue(IsEditingProperty, value);
    }

    private static void OnIsEditingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as PermissionCellEditBehavior;
        if (behavior?.AssociatedObject == null) return;

        if ((bool)e.NewValue)
        {
            // 进入编辑状态
            behavior.AssociatedObject.Focus();
            behavior.AssociatedObject.IsEditing = true;
        }
        else
        {
            // 退出编辑并提交
            behavior.AssociatedObject.IsEditing = false;
            behavior.AssociatedObject.CommitEdit();
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        // 绑定双击事件触发编辑
        AssociatedObject.MouseDoubleClick += OnCellDoubleClick;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.MouseDoubleClick -= OnCellDoubleClick;
    }

    private void OnCellDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        IsEditing = true;
    }
}

步骤2:在ViewModel中添加控制编辑的属性

private bool _isPermissionEditing;
public bool IsPermissionEditing
{
    get => _isPermissionEditing;
    set => SetProperty(ref _isPermissionEditing, value); // 假设你已实现INotifyPropertyChanged
}

private void ExecuteUpdatePermissionCommand(PermissionLevel selectedPermission)
{
    // 更新权限
    SelectedUsersModule.PermissionLevel = selectedPermission;
    // 结束编辑
    IsPermissionEditing = false;
}

步骤3:在XAML中附加Behavior

首先添加Interactivity命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

然后修改权限列的CellStyle:

<DataGridTemplateColumn Header="Permission Level" 
                        HeaderStyle="{StaticResource DataGridColumnHeaderStyle}" 
                        Width="*" 
                        CellTemplate="{StaticResource PermissionTemplate}" 
                        CellEditingTemplate="{StaticResource EditingPermissionTemplate}">
    <DataGridTemplateColumn.CellStyle>
        <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
            <!-- 绑定ViewModel的IsPermissionEditing属性 -->
            <Setter Property="local:PermissionCellEditBehavior.IsEditing" 
                    Value="{Binding DataContext.IsPermissionEditing, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=TwoWay}"/>
            <i:Interaction.Behaviors>
                <local:PermissionCellEditBehavior/>
            </i:Interaction.Behaviors>
        </Style>
    </DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>

这样双击单元格时Behavior会触发编辑,点击按钮后ViewModel更新IsPermissionEditing为false,Behavior就会让单元格退出编辑状态。


额外提示

如果不想依赖DataGrid的编辑机制,还可以用DataTemplateSelector结合每个数据项的IsEditing属性,完全自定义模板切换逻辑。这种方式更灵活,但需要给每个数据项添加编辑状态属性,适合复杂场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:40:29