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

WPF中TextBox失去焦点时修改StringFormat以显示小数

实现TextBox失去焦点时才显示小数格式的方案

你的核心需求是让TextBox在**编辑状态(获得焦点)**时显示用户的原始输入,失去焦点后再以N2格式显示小数,同时允许输入为空。目前的绑定方式因为用了UpdateSourceTrigger=PropertyChanged和绑定内的StringFormat,导致输入过程中就会自动格式化,干扰编辑体验。下面是具体的解决步骤:

步骤1:创建焦点感知的格式转换器

我们需要一个转换器,根据TextBox的焦点状态动态切换显示格式。这个转换器会处理两种情况:

  • 获得焦点:显示原始输入(如果是格式化后的小数,会自动还原成不带末尾零的数字字符串)
  • 失去焦点:将有效数字格式化为N2格式,无效输入/空值保持原样

创建一个实现IMultiValueConverter的转换器类:

using System;
using System.Globalization;
using System.Windows.Data;

public class FocusDecimalFormatConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // 确保输入参数正确
        if (values.Length != 2 || values[0] is not string input)
            return values[0] ?? string.Empty;

        bool isFocused = (bool)values[1];

        if (isFocused)
        {
            // 有焦点时,还原原始数字格式(去掉末尾的.00)
            if (decimal.TryParse(input, out decimal number))
            {
                string rawNumber = number.ToString();
                // 去掉末尾的零和可能的小数点
                return rawNumber.TrimEnd('0').TrimEnd('.');
            }
            return input;
        }
        else
        {
            // 失去焦点时,格式化为N2
            if (decimal.TryParse(input, out decimal number))
            {
                return number.ToString("N2", culture);
            }
            return input;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        // 将输入值直接返回给源属性,保持原始输入
        return new object[] { value as string ?? string.Empty, Binding.DoNothing };
    }
}

步骤2:在XAML中声明转换器

在你的Window/UserControl的Resources里注册这个转换器:

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

注意:local是你的转换器所在命名空间的前缀,需要根据实际情况调整。

步骤3:修改TextBox的绑定逻辑

移除原来绑定中的StringFormat和UpdateSourceTrigger=PropertyChanged,改用MultiBinding同时绑定AddItem属性和TextBox自身的IsFocused状态,并且设置UpdateSourceTrigger=LostFocus(确保只有失去焦点时才更新源):

<DataGridTemplateColumn Header="Add-Item" Width="2.25*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBox Margin="6,5,4,5" 
                     helpers:TextBoxExtension.ValidationType="DecimalSpecialCharacter">
                <TextBox.Text>
                    <MultiBinding Converter="{StaticResource FocusDecimalFormatConverter}"
                                  Mode="TwoWay"
                                  UpdateSourceTrigger="LostFocus">
                        <Binding Path="AddItem" Mode="TwoWay"/>
                        <Binding RelativeSource="{RelativeSource Self}" Path="IsFocused"/>
                    </MultiBinding>
                </TextBox.Text>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="PreviewKeyUp" >
                        <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

关键逻辑说明

  1. MultiBinding:同时传递AddItem的值和TextBox的焦点状态给转换器,让转换器能动态判断显示格式。
  2. UpdateSourceTrigger=LostFocus:避免输入过程中频繁更新源属性,只有用户完成输入离开TextBox时才更新,保证编辑流畅。
  3. 转换器的处理:
    • 编辑时:如果是格式化后的小数(比如123.00),会自动还原为123,方便用户继续编辑。
    • 失去焦点后:有效数字自动格式化为N2(比如123变成123.00),空值或无效输入保持原样,符合你的需求。

这样就能完美实现你想要的效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:52:27