采用的方法是使用Nullable<double>代替double 。
Nullable<double>和double的操纵对用户来说是透明的,可以无差别的混合使用它们。 但是Nullable<double>多了一个可以判断值类型是否有效的好处,这个体现到前台的好处就是TextBox可以显示空白。
object d1 = 1.2;
var b1 = d1 is Nullable<double>; //true
var b2 = d1 is double; //true
但是这样写也有一个问题:当文本框的值被删除时,TextBox会显示红色边框。接下来怎么解决这个问题呢,加一个转换器就可以了。转换器代码
public class StringEmptyToNull : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string str && string.IsNullOrWhiteSpace(str))
{
return null;
}
return value;
}
}
加入转换器前:
加入转换器后:
所有测试代码:
前台:
<Window.Resources>
<local:StringEmptyToNull x:Key="Converter"></local:StringEmptyToNull>
</Window.Resources>
<Grid>
<StackPanel Margin="5" Orientation="Horizontal" VerticalAlignment="Center">
<TextBox Text="{Binding A,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource Converter}}" VerticalContentAlignment="Center" Width="60" Height="30" VerticalAlignment="Top"></TextBox>
<TextBlock Text="+" Height="30" VerticalAlignment="Top" Margin="5"></TextBlock>
<TextBox Text="{Binding B,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource Converter}}" VerticalContentAlignment="Center" Width="60" Height="30" VerticalAlignment="Top"></TextBox>
<TextBlock Text="=" Margin="5"></TextBlock>
<TextBox Text="{Binding C,UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center" Width="60" Height="30" VerticalAlignment="Top" IsReadOnly="True"></TextBox>
</StackPanel>
</Grid>
后台:
/// <summary>
/// WinInteractive.xaml 的交互逻辑
/// </summary>
public partial class WinInteractive : Window
{
public WinInteractive()
{
InitializeComponent();
this.DataContext = new InteractiveItem();
}
}
public class InteractiveItem : INotifyPropertyChanged
{
#region 通知接口实现
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetPropertyValue<T>(ref T origin, T newValue, [CallerMemberName] string propertyName = "")
{
origin = newValue;
RaisePropertyChanged(propertyName);
}
#endregion
private Nullable<double> m_A;
/// <summary>
/// A参数
/// </summary>
public Nullable<double> A
{
get { return this.m_A; }
set
{
this.m_A = value;
C = m_A + m_B;
RaisePropertyChanged(nameof(A));
}
}
private Nullable<double> m_B;
/// <summary>
/// B参数
/// </summary>
public Nullable<double> B
{
get { return this.m_B; }
set
{
this.m_B = value;
C = m_A + m_B;
RaisePropertyChanged(nameof(B));
}
}
private Nullable<double> m_C;
/// <summary>
/// C参数
/// </summary>
public Nullable<double> C
{
get { return this.m_C; }
set
{
this.m_C = value;
RaisePropertyChanged(nameof(C));
}
}
}