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

如何在WPF DataGrid中便捷设置并获取Decimal类型单元格新值?

WPF DataGrid Decimal类型单元格便捷小数输入方案

问题场景

将DataGrid单元格绑定到ViewModel的Decimal类型属性,已设置双向绑定和UpdateSourceTrigger=PropertyChanged,但输入小数时存在操作痛点:必须先输入整数部分,再返回添加小数点;直接输入小数点且无后续数字时,会被验证视为整数,操作繁琐。

解决方案

1. 自定义绑定转换器处理特殊输入

通过实现IValueConverter,在转换回源时处理纯小数点、空输入等特殊情况,避免验证失败:

public class DecimalInputConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is decimal decimalValue ? decimalValue.ToString(culture) : string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var input = value.ToString().Trim();
        
        // 处理纯小数点,转换为0.0
        if (input == ".")
            return 0.0m;
        // 处理空输入,返回0.0
        if (string.IsNullOrEmpty(input))
            return 0.0m;
        // 正常转换小数
        if (decimal.TryParse(input, NumberStyles.Any, culture, out var result))
            return result;
        
        // 转换失败时不更新源
        return Binding.DoNothing;
    }
}

在XAML中引用转换器:

<Window.Resources>
    <local:DecimalInputConverter x:Key="DecimalInputConverter"/>
</Window.Resources>

<DataGridTextColumn Header="Cantidad" 
                    Binding="{Binding Cantidad, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DecimalInputConverter}}" 
                    IsReadOnly="false"/>

2. 使用自定义编辑模板(推荐)

替换默认的文本框编辑模板,使用带输入限制的TextBox或第三方掩码控件,提升输入体验:

方案A:自定义TextBox输入限制

<DataGridTemplateColumn Header="Cantidad">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Cantidad}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Cantidad, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                     PreviewTextInput="DecimalTextBox_PreviewTextInput"
                     DataObject.Pasting="DecimalTextBox_Pasting"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

后台代码处理输入验证:

private void DecimalTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    var textBox = sender as TextBox;
    // 只允许数字和单个小数点
    if (!char.IsDigit(e.Text, 0) && e.Text != ".")
    {
        e.Handled = true;
        return;
    }
    if (e.Text == "." && textBox.Text.Contains("."))
    {
        e.Handled = true;
    }
}

private void DecimalTextBox_Pasting(object sender, DataObjectPastingEventArgs e)
{
    if (e.DataObject.GetDataPresent(typeof(string)))
    {
        var text = (string)e.DataObject.GetData(typeof(string));
        if (!text.All(c => char.IsDigit(c) || c == ".") || text.Count(c => c == ".") > 1)
        {
            e.CancelCommand();
        }
    }
    else
    {
        e.CancelCommand();
    }
}

方案B:使用第三方掩码控件(如Extended WPF Toolkit)

<DataGridTemplateColumn Header="Cantidad">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Cantidad}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <xctk:MaskedTextBox Mask="###0.##" 
                                Value="{Binding Cantidad, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                ValueType="{x:Type system:Decimal}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

3. 调整绑定更新触发时机

如果不需要实时更新ViewModel,可将UpdateSourceTrigger改为LostFocus,这样在编辑过程中纯小数点不会立刻触发源更新,直到单元格失去焦点再完成转换,避免中间状态的验证问题:

<DataGridTextColumn Header="Cantidad" 
                    Binding="{Binding Cantidad, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" 
                    IsReadOnly="false"/>

4. 自定义验证规则允许临时输入

添加自定义ValidationRule,允许空字符串或纯小数点作为临时输入,避免编辑过程中出现验证错误提示:

public class DecimalValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var input = value.ToString().Trim();
        // 允许临时的空输入或纯小数点
        if (string.IsNullOrEmpty(input) || input == ".")
            return ValidationResult.ValidResult;
        // 验证有效小数
        return decimal.TryParse(input, out _) ? ValidationResult.ValidResult 
                                              : new ValidationResult(false, "请输入有效的小数");
    }
}

XAML中绑定添加验证规则:

<DataGridTextColumn Header="Cantidad">
    <DataGridTextColumn.Binding>
        <Binding Path="Cantidad" Mode="TwoWay" UpdateSourceTrigger=PropertyChanged>
            <Binding.ValidationRules>
                <local:DecimalValidationRule ValidationStep="RawProposedValue"/>
            </Binding.ValidationRules>
        </Binding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>

内容的提问来源于stack exchange,提问作者Álvaro García

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:05:21