一、何为数据绑定

场景:考虑一个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>
 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 }

 五、转换器

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

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

转换器包括单值转换器和多值转换器。单值转换器需要实现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 }
 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>

现在考虑以下场景,我们有一个椭圆,椭圆的颜色是根据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 }
 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>

六、绑定的删除

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

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

WPF---数据绑定(一)的更多相关文章

  1. WPF 数据绑定Binding

    什么是数据绑定? Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互. 通过数据绑定,您可以对两个不同对象 ...

  2. WPF数据绑定Binding(二)

    WPF数据绑定Binding(二) 1.UI控件直接的数据绑定 UI对象间的绑定,也是最基本的形式,通常是将源对象Source的某个属性值绑定 (拷贝) 到目标对象Destination的某个属性上. ...

  3. WPF——数据绑定(一)什么是数据绑定

    注意:本人初学WPF,文中可能有表达或者技术性问题,欢迎指正!谢谢! 一:什么是数据绑定? “Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简 ...

  4. 剖析WPF数据绑定机制

    引言 WPF框架采取的是MVVM模式,也就是数据驱动UI,UI控件(Controls)被严格地限制在表示层内,不会参与业务逻辑的处理,只是通过数据绑定(Data Binding)简单忠实地表达与之绑定 ...

  5. WPF 10天修炼 第十天- WPF数据绑定

    WPF数据绑定 数据绑定到元素属性是将源对象指定为一个WPF元素,并且源属性是一个依赖属性,依赖属性内置了变更通知.当改变源对象依赖属性值之后,绑定目标可以立即得到更新,开发人员不需要手动编写响应事件 ...

  6. 微软原文翻译:适用于.Net Core的WPF数据绑定概述

    原文链接,大部分是机器翻译,仅做了小部分修改.英.中文对照,看不懂的看英文. Data binding overview in WPF 2019/09/19 Data binding in Windo ...

  7. C#-WPF数据绑定基础(一)

    前言:WPF数据绑定技术有效的提高了程序的容错率,可以最大程度的保持程序的健壮性,从而降低程序在使用过程中崩掉的可能性. 接下来,我将分享一下我在写测量程序过程中所用到的数据绑定方面的知识 首先,我所 ...

  8. C#WPF数据绑定模板化操作四步走

    前言:WPF数据绑定对于WPF应用程序来说尤为重要,本文将讲述使用MVVM模式进行数据绑定的四步走用法: 具体实例代码如下: 以下代码仅供参考,如有问题请在评论区留言,谢谢 1 第一步:声明一个类用来 ...

  9. WPF 数据绑定 1_1 基础知识&绑定到元素属性

    A.数据绑定基础: 数据源对象:WPF将从该对象中提取信息,交由目标对象进行显示. 目标对象:从数据源中提取信息,并赋给该对象的属性. B.绑定到元素属性 最简单的绑定情形则是将一个源对象指定为一个W ...

  10. WPF 数据绑定基础

    纯理论,可能会枯燥. .net 技术群: 199281001 ,欢迎加入. 1.目标对象一定是派生自DependencyObject的对象,并且目标属性必须是依赖属性,否则数据绑定操作将会失   败. ...

随机推荐

  1. C语言:编程求任意月份的天数

    闰年问题,因为二月份的天数与闰年有关.闰年的判断依据是:若某年能被4整除,但不能被100整除,则这一年是闰年:若某年能被400整除,则这一年也是闰年 #include <stdio.h> ...

  2. PYTHON 连接SQL2008 导出到EXCEL

    #import pymssql from datetime import datetime import pyodbc import os current_dir = os.path.abspath( ...

  3. python 查看导入模块的函数和方法

    将twain.pyd复制到Python27 \ Lib \ site-packages 首先 import XXX(包括pyd的文件名)print(dir(XXX))print(help(xxx)) ...

  4. 每天五分钟Go - 数组

    //数组的声明,默认为0值 var a1 [2]int fmt.Println(a1) //数组的长度 fmt.Println(len(a1)) //遍历数组 for i, v := range a1 ...

  5. Nodejs 处理异步(获取异步数据并处理)的方法

    方法1. 回调函数方式 将异步方法如readFile封装到一个自定义函数中,通过将异步方法得到的结果传给自定义方法的回调函数参数.具体如下(以fs模块的readFile方法为例): //封装 var ...

  6. 基于小熊派Hi3861鸿蒙开发的IoT物联网学习【五】

    BearPi-HM_Nano开发板鸿蒙OS内核编程开发--消息队列 什么是消息队列?        答:消息队列中间件是分布式系统中重要的组件,主要解决应用耦合.异步消息.流量削锋等问题.实现高性能. ...

  7. JAVA学习笔记之基础概念(一)

    一.Java 简介: Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称. 由 James Gosling和同 ...

  8. Querydsl与SpringBoot集成

    Querydsl为大多数数据库提供了一种基于Java的类型安全,类SQL的查询方式.相比JPA,Querydsl能提供更加强大的查询方式,比如关联查询.相比MyBatis,Querydsl省去了XML ...

  9. springboot整合mybatis源码分析

    springboot整合mybatis源码分析 本文主要讲述mybatis在springboot中是如何被加载执行的,由于涉及的内容会比较多,所以这次只会对调用关系及关键代码点进行讲解,为了避免文章太 ...

  10. 使用C#winform编写渗透测试工具--端口扫描

    使用C#winform编写渗透测试工具--端口扫描器 主要介绍使用C#winform编写渗透测试工具--端口扫描器,端口扫描器则是一种检测服务器或者主机虚拟端口是开启或关闭的工具.由于连接到局域网或互 ...