WPF---数据绑定(一)

一、何为数据绑定

场景:考虑一个Window上有一个TextBox和一个Slider两个元素,当我拖动滑动条的时候,会在TextBox中显示当前滑动条的数值;当我们在TextBox中输入一个有效值,滑动条

中的滑块会滑到TextBox中输入的值所对应的位置。

定义:数据绑定可以理解为两个对象之间的一种关联,对象中的某个属性总是保持同步于另个对象的某个属性值。我们可以形象的把绑定比作一个桥梁,它负责同步桥头两侧的物体。

保持同步的数据元素必须是属性,一个叫源属性,一个叫目标属性;

目标属性必须是一个依赖属性。

二、如何绑定元素对象

关于上面滑动条和文本框的绑定,我们可以用以下Xaml代码实现:

<Window x:Class="BindingDemo1.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:BindingDemo1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider}" ></TextBox>
            <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
        </StackPanel>
    </Grid>
</Window>

等价的后台代码实现如下:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace BindingDemo1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
           // Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
            Binding binding = new Binding("Value") { ElementName = "sldrSlider" };
            tbx.SetBinding(TextBox.TextProperty, binding);
        }
    }
}

后台代码主要完成了以下功能:
 1)创建一个binding对象;

 2)设置了binding对象的Source和Path值;

 3)调用了目标(textbox)的SetBinding方法创建一个binding表达式,它连接了binding对象和目标依赖属性。

三、数据绑定的方向

我们可以通过设置Binding对象Mode属性控制数据绑定的方向

OneWay:数据源改变时,更新目标;

TwoWay:双向更新;

OneWayToSource:目标改变时,更新数据源;

OneTime:只更新目标一次,使用数据源的初值,以后目标不再被更新;

Default:使用目标的默认绑定模式。

四、触发器---更新数据源的时机

仍然考虑上面滑动条和文本框的绑定关系,我们会发现当文本框的数值改变后,滑动条的滑块不会立即改变,而是在文本框失去焦点的时候,才会改变。

这就涉及到当目标属性变化的时候,数据源如何以及何时变化。

关于数据的更新方向和时机,可以参见下图:

当目标依赖属性发生变化,我们可以利用Binding对象的UpdateSourceTrigger属性来控制何时更新数据源,UpdateSourceTrigger属性值包括以下:

注:UpdateSourceTrigger属性值不影响目标的更新方式,它仅仅控制TwoWay模式或OneWayToSource模式的绑定更新源的方式。

而文本框正是使用LostFocus方式从目标向源进行更新的。

如果要完全控制源对象的更新时机,则可以选择UpdateSourceTrigger.Explicit模式

此时就需要额外编写代码手动触发更新。可以添加一个Apply按钮,并在按钮的Click事件处理程序中调用BindingExpression.UpdateSource方法立即更新数据源。

参考代码以下:

 1 <Window x:Class="BindingDemo1.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:BindingDemo1"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="350" Width="525">
 9     <Grid>
10         <StackPanel>
11             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit}" ></TextBox>
12             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
13             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
14         </StackPanel>
15     </Grid>
16 </Window>
View Code
 1 using System.Windows;
 2 using System.Windows.Controls;
 3 using System.Windows.Data;
 4 
 5 namespace BindingDemo1
 6 {
 7     /// <summary>
 8     /// Interaction logic for MainWindow.xaml
 9     /// </summary>
10     public partial class MainWindow : Window
11     {
12         public MainWindow()
13         {
14             InitializeComponent();
15            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
16            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
17            //tbx.SetBinding(TextBox.TextProperty, binding);
18         }
19 
20         private void Button_Click(object sender, RoutedEventArgs e)
21         {
22             //获得应用于文本框上的绑定
23             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
24             //调用UpdateSource更新源对象
25             be.UpdateSource();
26         }
27     }
28 }
View Code

 五、转换器

上面的例子中,当拖动滑动条的时候,文本框中显示的数字会显示好多位小数,现在我们想让在文本框中只显示两位小数,这时候就需要转换器来实现了。

定义:转化器是一个类,用于拦截数据源和目标之间的数据,拦截之后,就可以按照我们的意愿对数据进行操作。

转换器包括单值转换器多值转换器。单值转换器需要实现IValueConverter接口,多值转换器需要实现IMultiValueConverter接口。

对于上面的需求,我们可以使用单值转换器,参考代码如下:

 1 using System;
 2 using System.Globalization;
 3 using System.Windows;
 4 using System.Windows.Controls;
 5 using System.Windows.Data;
 6 
 7 namespace BindingDemo1
 8 {
 9     /// <summary>
10     /// Interaction logic for MainWindow.xaml
11     /// </summary>
12     public partial class MainWindow : Window
13     {
14         public MainWindow()
15         {
16             InitializeComponent();
17            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
18            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
19            //tbx.SetBinding(TextBox.TextProperty, binding);
20         }
21 
22         private void Button_Click(object sender, RoutedEventArgs e)
23         {
24             //获得应用于文本框上的绑定
25             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
26             //调用UpdateSource更新源对象
27             be.UpdateSource();
28         }
29     }
30     public class SliderValue2StringConverter:IValueConverter
31     {
32         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
33         {
34             double valueFromSource = (double)value;
35             return valueFromSource.ToString("F2");//保留两位小数
36         }
37  
38         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
39         {
40             throw new NotImplementedException("Method ConvertBack not implemented");
41         }
42     }
43 }
View Code
 1 <Window x:Class="BindingDemo1.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:BindingDemo1"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="350" Width="525">
 9     <Window.Resources>
10         <local:SliderValue2StringConverter x:Key="s2vCvt"></local:SliderValue2StringConverter>
11     </Window.Resources>
12     <Grid>
13         <StackPanel>
14             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit,Converter={StaticResource ResourceKey=s2vCvt}}" ></TextBox>
15             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
16             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
17         </StackPanel>
18     </Grid>
19 </Window>
View Code

现在考虑以下场景,我们有一个椭圆,椭圆的颜色是根据RGB三个不同的分量变化的,我们让三个滑动条分别控制RGB三个分量,下面就用多值转换器进行实现。

 1 using System;
 2 using System.Globalization;
 3 using System.Windows;
 4 using System.Windows.Controls;
 5 using System.Windows.Data;
 6 using System.Windows.Media;
 7 
 8 namespace BindingDemo1
 9 {
10     /// <summary>
11     /// Interaction logic for MainWindow.xaml
12     /// </summary>
13     public partial class MainWindow : Window
14     {
15         public MainWindow()
16         {
17             InitializeComponent();
18            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
19            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
20            //tbx.SetBinding(TextBox.TextProperty, binding);
21         }
22 
23         private void Button_Click(object sender, RoutedEventArgs e)
24         {
25             //获得应用于文本框上的绑定
26             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
27             //调用UpdateSource更新源对象
28             be.UpdateSource();
29         }
30     }
31     public class SliderValue2StringConverter:IValueConverter
32     {
33         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
34         {
35             double valueFromSource = (double)value;
36             return valueFromSource.ToString("F2");//保留两位小数
37         }
38  
39         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
40         {
41             throw new NotImplementedException("Method ConvertBack not implemented");
42         }
43     }
44     public class Rgb2ColorConverter : IMultiValueConverter
45     {
46         //正向修改,整合颜色值
47         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
48         {
49             if (values == null || values.Length < 3)
50                 return null;
51             byte r = System.Convert.ToByte(values[0]);
52             byte g = System.Convert.ToByte(values[1]);
53             byte b = System.Convert.ToByte(values[2]);
54             Color myColor = Color.FromRgb(r, g, b);
55             SolidColorBrush myBrush = new SolidColorBrush(myColor);
56             return myBrush;
57         }
58         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
59         {
60             throw new NotImplementedException("Method ConvertBack not implemented");
61         }
62 
63     }
64 }
View Code
 1 <Window x:Class="BindingDemo1.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:BindingDemo1"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="350" Width="525">
 9     <Window.Resources>
10         <local:SliderValue2StringConverter x:Key="s2vCvt"></local:SliderValue2StringConverter>
11     </Window.Resources>
12     <Grid>
13         <Grid.ColumnDefinitions>
14             <ColumnDefinition Width="191*"/>
15             <ColumnDefinition Width="326*"/>
16         </Grid.ColumnDefinitions>
17         <Grid.RowDefinitions>
18             <RowDefinition Height="111*"/>
19             <RowDefinition Height="209*"/>
20         </Grid.RowDefinitions>
21         <StackPanel>
22             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit,Converter={StaticResource ResourceKey=s2vCvt}}" ></TextBox>
23             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
24             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
25        
26         </StackPanel>
27         <StackPanel Grid.Column="1">
28             <StackPanel Orientation="Horizontal">
29                 <Label Content="R:"></Label>
30                 <Slider Name="sldR" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"></Slider>
31             </StackPanel>
32             <StackPanel Orientation="Horizontal">
33                 <Label Content="G:"></Label>
34                 <Slider Name="sldG" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"></Slider>
35             </StackPanel>
36             <StackPanel Orientation="Horizontal">
37                 <Label Content="B:"></Label>
38                 <Slider x:Name="sldB" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"/>
39             </StackPanel>
40             <StackPanel Orientation="Horizontal">
41                 <Label Content="O:"></Label>
42                 <Slider Name="sldO" Foreground="Red" Width="300" Minimum="0" Maximum="1" Ticks="0.1" Value="0.5"></Slider>
43             </StackPanel>
44 
45         </StackPanel>
46         <Ellipse Grid.Row="1" Grid.Column="1" Stroke="Pink">
47             <Ellipse.Resources>
48                 <local:Rgb2ColorConverter x:Key="colorCvt"></local:Rgb2ColorConverter>
49             </Ellipse.Resources>
50             <Ellipse.Fill>
51                 <MultiBinding Converter="{StaticResource colorCvt}">
52                     <Binding ElementName="sldR" Path="Value"></Binding>
53                     <Binding ElementName="sldG" Path="Value"></Binding>
54                     <Binding ElementName="sldB" Path="Value"></Binding>
55                 </MultiBinding>
56             </Ellipse.Fill>
57             <Ellipse.Opacity>
58                 <Binding Path="Value" ElementName="sldO" >
59                     
60                 </Binding>
61             </Ellipse.Opacity>
62         </Ellipse>
63     </Grid>
64 </Window>
View Code

六、绑定的删除

我们可以使用类BindingOperations中的以下函数来删除绑定

public static void ClearAllBindings(DependencyObject target);
public static void ClearBinding(DependencyObject target, DependencyProperty dp);

原文地址:https://www.cnblogs.com/3xiaolonglong/p/9717605.html