WPF的IValueConverter用于校验和格式化TextBox的数字输入

发布于:2024-07-05 ⋅ 阅读:(19) ⋅ 点赞:(0)

         在数据绑定(Data Binding)的上下文中,我们经常使用继承 IValueConverter 接口的类,用于在源值和目标值之间进行转换。该接口定义了两个方法:Convert 和 ConvertBack,这两个方法分别用于从源值到目标值的转换和从目标值回到源值的转换(如果绑定支持双向绑定)。

        TextBox 控件的 UpdateSourceTrigger 属性用于控制何时更新绑定源的值,它有以下4个可选值:

  • PropertyChanged:当 TextBox 的内容发生任何变化时,都会更新绑定源。这是默认值,提供了即时反馈,但可能会增加应用程序的负载,因为每次击键都会触发更新。主要用于实时校验文本输入。
  • LostFocus:当 TextBox 失去焦点时,更新绑定源。这减少了不必要的更新,但可能意味着在用户完成输入之前,绑定源的值不会反映最新的更改。
  • Explicit:不会自动更新绑定源。你需要显式调用 BindingExpression 的 UpdateSource 方法来更新绑定源。
  • Default:使用绑定目标的默认 UpdateSourceTrigger 值。对于 TextBox,这通常是 PropertyChanged

        TextBox 控件的绑定模式(Mode)通常不是 TextBox 控件本身的直接属性,而是与数据绑定(Data Binding)相关的属性。当在 TextBox 的 Text 属性上使用数据绑定时,有时需要设置 Binding 对象的 Mode 属性来控制数据的流动方向。它有如下5个可选值:

  1. OneWay:这是单向绑定的默认模式。当源属性的值改变时,目标属性(即 TextBox 的 Text 属性)的值会自动更新。但是,对目标属性的更改不会传播回源属性。

  2. TwoWay:这是双向绑定的模式。当源属性或目标属性的值改变时,另一个属性的值也会自动更新。在 TextBox 的上下文中,这意味着当你在文本框中输入文本时,绑定的源属性会更新;同样地,如果源属性的值在代码中被改变,文本框中的内容也会更新。

  3. OneWayToSource:这是另一种单向绑定模式,但与 OneWay 相反。在这种模式下,当目标属性(TextBox 的 Text 属性)的值改变时,源属性的值也会更新,但源属性的变化不会影响到目标属性。

  4. OneTime:在这种模式下,数据只在绑定时从源传输到目标一次。之后,源属性的变化不会反映到目标属性上,并且目标属性的变化也不会尝试回写到源属性。

  5. Default:这表示使用绑定目标的默认模式。对于 TextBox 的 Text 属性,默认模式通常是 TwoWay,但这也可能取决于具体的绑定上下文和父控件的设置。

 

        如下xaml页面中,左边的TextBox使用Converter属性,绑定值转换器,右边的则没有。

<Window x:Class="TextConverterTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TextConverterTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:NumericToStringConverter x:Key="NToSConverter"/>
        <Style TargetType="TextBox">
            <Setter Property="Height" Value="80"></Setter>
            <Setter Property="Width" Value="180"></Setter>
            <Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
            <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
            <Setter Property="FontSize" Value="20"></Setter>
        </Style>
    </Window.Resources>
    <Grid Height="100" Width="400">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Path=TextBoxLeftStr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NToSConverter}}"></TextBox>
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=TextBoxRightStr, Mode=TwoWay}, UpdateSourceTrigger=PropertyChanged"></TextBox>
    </Grid>
</Window>

         添加TextBox的Path绑定的字段属性。在构造函数中,必须要有【DataContext = this;】这行代码,用于获取或设置元素参与数据绑定时的数据上下文。

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public string TextBoxLeftStr { get; set; }
    public string TextBoxRightStr { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;//必须要有,关联上下文
    }
}

        IValueConverter接口的具体实现: 

public class NumericToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    try
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return "";
        }
        else if (value.ToString().Last() == '.')
        {
            return value.ToString();
        }

        decimal decimalValue = System.Convert.ToDecimal(value);
        string format = decimalValue % 1 == 0 ? "0" : "0.0"; // 如果小数部分为0则不显示小数,否则显示一位小数  
        return decimalValue.ToString(format, CultureInfo.InvariantCulture);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return "";
    }
}

// ConvertBack方法可能不需要,因为通常TextBox到数值的转换是单向的  
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    try
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return "";
        }
        else if (value.ToString().Last() == '.')
        {
            return value.ToString();
        }

        decimal decimalValue = System.Convert.ToDecimal(value);
        string format = decimalValue % 1 == 0 ? "0" : "0.0"; // 如果小数部分为0则不显示小数,否则显示一位小数  
        return decimalValue.ToString(format, CultureInfo.InvariantCulture);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return "";
    }
}
}

        在xaml中引入资源类:

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

         实现效果:左TextBox最多只能输入1位小数。且左右两个TextBox均不能输入除数字和小数点以外的字符。


网站公告

今日签到

点亮在社区的每一天
去签到