为何无法在WPF TextBox中输入小数?如何解决?
WPF TextBox绑定decimal?无法输入小数点的问题及解决方法
问题重现
ViewModel代码
public class ViewModelData : INotifyPropertyChanged { private decimal? myValue; public decimal? MyValue { get { return myValue; } set { myValue = value; OnPropertyChanged(nameof(MyValue)); } } public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
XAML代码
<TextBox Name="MyValueBox" Text="{Binding MyValue, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="112" Margin="0,96,0,0"/>
问题现象:输入1.0时,先输入1后无法直接输入小数点;但先输入其他内容(如text1.0)或在已输入的数字中间插入小数点(如先输10再在中间加.变成1.0)则可以正常工作。
原因解析
核心问题在于UpdateSourceTrigger=PropertyChanged的行为:每输入一个字符就会触发数据源更新。当输入1.时,WPF默认的类型转换器会尝试将字符串"1."转换为decimal?类型,但该字符串不符合有效的decimal格式,转换失败,导致数据源不更新,TextBox会自动回退到之前的有效值"1",小数点因此被清除。而在数字中间插入小数点得到"1.0"时,字符串是有效的decimal格式,转换成功,所以能保留输入内容。
解决方案
方案1:调整UpdateSourceTrigger触发时机
将绑定的UpdateSourceTrigger改为LostFocus,这样仅当TextBox失去焦点时才更新数据源,输入过程中不会触发类型转换,自然可以正常输入小数点:
<TextBox Name="MyValueBox" Text="{Binding MyValue, UpdateSourceTrigger=LostFocus}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="112" Margin="0,96,0,0"/>
方案2:实现自定义值转换器
创建自定义转换器,处理输入过程中的中间状态(如单个小数点),避免转换失败导致的回退:
public class DecimalNullableConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return value is decimal? dec && dec.HasValue ? dec.ToString(culture) : string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var input = value as string; if (string.IsNullOrWhiteSpace(input)) return null; // 允许输入单个小数点,可根据需求返回0或null if (input == ".") return decimal.Zero; if (decimal.TryParse(input, NumberStyles.Any, culture, out var result)) return result; // 转换失败时返回Binding.DoNothing,避免TextBox回退到旧值 return Binding.DoNothing; } }
在XAML中引用转换器:
<Window.Resources> <local:DecimalNullableConverter x:Key="DecimalNullableConverter"/> </Window.Resources> <TextBox Name="MyValueBox" Text="{Binding MyValue, Converter={StaticResource DecimalNullableConverter}, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="112" Margin="0,96,0,0"/>
方案3:使用掩码输入控件
借助WPF Toolkit或第三方库中的MaskedTextBox,设置合适的掩码(如0.00)来规范输入格式,从根源避免无效输入的转换问题。
内容的提问来源于stack exchange,提问作者markzzz
相关产品推荐
相关产品推荐

