数据绑定是WPF应用的关键.下面通过一段代码来重温基本绑定

1.基本数据绑定

1.1 提前准备的内容

  • 数据实体类 Customer ,通过继承INotifyPropertyChanged接口,实现PropertyChangedEventHandler 委托的方法
using System;
using System.ComponentModel;
namespace SimpleBinding
{
    public class Customer : INotifyPropertyChanged
    {
        private string _name;
        public Customer()
        {
        }

        public Customer( string value)
        {
            _name = value;
        }

        public string CustomerName
        {
            get { return _name; }
            set
            {
                _name = value;
                // Call OnPropertyChanged whenever the property is updated
                OnPropertyChanged("CustomerName");
            }
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
                OnPropertyChanged("Age");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            var handler = PropertyChanged;
            handler?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

1.2 前台数据绑定

  • Step 1 定义数据源
<Window.Resources>
        <!--绑定的资源对象 Person,必须有一个无参构造函数 -->
        <local:Customer x:Key="MyDataSource" CustomerName="Joe" Age="10" />
</Window.Resources>
  • Step2 绑定到界面控件
<Border Margin="5" BorderBrush="Red" BorderThickness="2" Padding="8" CornerRadius="20">
        <StackPanel  >
            <Label>请输入姓名</Label>
            <TextBox>
                <TextBox.Text>
                    <Binding Source="{StaticResource MyDataSource}" Path="CustomerName" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>
            </TextBox>

            <Label>请输入年龄</Label>
            <TextBox>
                <TextBox.Text>
                    <Binding Source="{StaticResource MyDataSource}" Path="Age" UpdateSourceTrigger="PropertyChanged">
                    </Binding>
                </TextBox.Text>
            </TextBox>

            <Label>输入的信息如下:</Label>
            
            <TextBlock>
                <Run Text="姓名:"/>
                <TextBlock Text="{Binding Source={StaticResource MyDataSource}, Path=CustomerName}" />
                <Run Text="年龄:"/>
                <TextBlock Text="{Binding Source={StaticResource MyDataSource}, Path=Age}" />
               
            </TextBlock>
        </StackPanel>
  • Step3 运行程序,可以看到,改变数据,相关绑定内容会随之变化.
    WPF基础 数据绑定与验证_数据

1.3 数据验证

年龄输入10212,显然与实际不符,为更贴近实际,需要进一步增加验证功能.

  • 自定义验证类 AgeRangeRule.cs
    该类定义一个年龄的最大值和最小值,重写了验证规则
  public class AgeRangeRule : ValidationRule
    {
        public int Min { get; set; }
        public int Max { get; set; }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            var age = 0;
            try
            {
                if (((string)value).Length > 0)
                    age = int.Parse((string)value);
            }
            catch (Exception e)
            {
                return new ValidationResult(false, "只能输出数字" + e.Message);
            }

            if ((age < Min) || (age > Max))
            {
                return new ValidationResult(false,
                    "请按范围输入年龄: " + Min + " - " + Max + ".");
            }
            return new ValidationResult(true, null);
        }
    }
}
  • 修改窗口相关代码
    WPF基础 数据绑定与验证_xml_02
    修改后,xaml代码如下:
<Window x:Class="SimpleBinding.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:SimpleBinding"
        mc:Ignorable="d" Height="300" Width="300" Title="MainWindow"  >
    <Window.Resources>
        <!--绑定的资源对象 Person,必须有一个无参构造函数 -->
        <local:Customer x:Key="MyDataSource" CustomerName="Joe" Age="10" />
    </Window.Resources>


    <Border Margin="5" BorderBrush="Red" BorderThickness="2" Padding="8" CornerRadius="20">
        <StackPanel  >
            <Label>请输入姓名</Label>
            <TextBox>
                <TextBox.Text>
                    <Binding Source="{StaticResource MyDataSource}" Path="CustomerName" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>
            </TextBox>

            <Label>请输入年龄</Label>
            <TextBox>
                <TextBox.Text>
                    <Binding Source="{StaticResource MyDataSource}" Path="Age" UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <local:AgeRangeRule Min="10" Max="130"/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

            <Label>输入的信息如下:</Label>
            
            <TextBlock>
                <Run Text="姓名:"/>
                <TextBlock Text="{Binding Source={StaticResource MyDataSource}, Path=CustomerName}" />
                <Run Text="年龄:"/>
                <TextBlock Text="{Binding Source={StaticResource MyDataSource}, Path=Age}" />
                
            </TextBlock>

        </StackPanel>
    </Border>
</Window>

再次运行
WPF基础 数据绑定与验证_microsoft_03
可以看到,当年龄输出小于10或者大于130的数据时,输入呈红色警告,当输入数值超出正常值范围外时,下面的输入信息显示不再变化.起到了初步的验证效果,但这并不是我想要的

继续优化!!

1.4 数据验证再优化 (Business Layer Validation)

  • 资源中定义验证提供信息的样式
    WPF基础 数据绑定与验证_数据验证_04

  • 录入框TextBox 绑定定义的静态样式
    WPF基础 数据绑定与验证_数据_05

  • 效果如图,当出现错误时,鼠标在录入控件上悬停时,会出现提示框.提示信息来源于 AgeRangeRule 规则
    WPF基础 数据绑定与验证_数据验证_06

2.绑定到数据选择控件 DataPickBinding

WPF基础 数据绑定与验证_数据绑定_07

<Window x:Class="DataPickBinding.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:DataPickBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="16"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="DockPanel.Dock" Value="Top"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
        </Style>
        <Style TargetType="Canvas">
            <Setter Property="Height" Value="50"/>
            <Setter Property="Width" Value="50"/>
            <Setter Property="Margin" Value="8"/>
            <Setter Property="DockPanel.Dock" Value="Top"/>
        </Style>
        <Style TargetType="ComboBox">
            <Setter Property="Width" Value="150"/>
            <Setter Property="Margin" Value="8"/>
            <Setter Property="DockPanel.Dock" Value="Top"/>
        </Style>
    </Window.Resources>
    
    <Border Margin="10" BorderBrush="Silver" BorderThickness="3" Padding="8">
        <DockPanel>
            <TextBlock>Choose a Color:</TextBlock>
            <ComboBox Name="myComboBox" SelectedIndex="0">
                <ComboBoxItem>Green</ComboBoxItem>
                <ComboBoxItem>Blue</ComboBoxItem>
                <ComboBoxItem>Red</ComboBoxItem>
            </ComboBox>
            <Canvas Width="150" Height="40" >
                <Canvas.Background>
                    <Binding ElementName="myComboBox" Path="SelectedItem.Content"/>
                </Canvas.Background>
            </Canvas>
        </DockPanel>
    </Border>
</Window>


3.绑定到方法

新建TemperatureScale类,包含一个ConvertTemp方法
WPF基础 数据绑定与验证_microsoft_08
在xaml资源中定义表态方法引用,并定义2个参数初始值
WPF基础 数据绑定与验证_microsoft_09

WPF基础 数据绑定与验证_数据绑定_10