winform有binding, WPF也有binding,区别在哪呢?这里暂时不提。以前也检查接触WPF binding, 但为什么过段时间就忘记了呢?

可能主要原因自己的知识体系不够完善吧,下面我先总结下binding的用法,然后再深入挖掘binding的原理,最后再总结,这样希望自己能够对binding达到非常深刻的理解。

binding的用法:

  1)绑定控件属性。下面是将一个Slider的值绑定到一个Textbox上。

     <TextBox Grid.Row="1" Text="{Binding Path=Value,ElementName=slider1}"></TextBox>
            <Slider Grid.Row="2" x:Name="slider1" Maximum="100" Minimum="0"></Slider>

2)绑定多级路径,比如属性的属性,索引器等。

      <TextBox Grid.Row="2" x:Name="textbox2" Text="{Binding  Path=Text.Length,ElementName=textbox1,Mode=OneWay}"
                     BorderBrush="Black" Margin="5"></TextBox>
            <TextBox Grid.Row="3" x:Name="textbox3" Text="{Binding Path=Text[4],ElementName=textbox1,Mode=OneWay}"
                     BorderBrush="Red" Margin="5"></TextBox>

3)还可以判定集合,甚至是集合的集合元素。

      List<string> stringList = new List<string>(){"xiaowang","dabing","qizhi"};
            this.txtCollection1.SetBinding(TextBox.TextProperty, new Binding("/") { Source = stringList });
            this.txtCollection2.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = stringList,
                Mode = BindingMode.OneWay });
            this.txtCollection3.SetBinding(TextBox.TextProperty, new Binding("/[2]") { Source = stringList, Mode = BindingMode.OneWay });

this.txtCollection4.SetBinding(TextBox.TextProperty, new Binding("/Name") { Source = countryList });
            this.txtCollection5.SetBinding(TextBox.TextProperty, new Binding("/ProvinceList/Name")
            {
                Source = countryList,
            });
            this.txtCollection6.SetBinding(TextBox.TextProperty, new Binding("/ProvinceList/CityList/Name") { Source = countryList });

4)还可以没有Path的Binding,这里的路径直接用一个.就可以了。

<TextBox Grid.Row="1" Text="{Binding .,Source={StaticResource ResourceKey=myString}}"></TextBox>

5)使用DataContext作为源:

<StackPanel Grid.Row="1">
                <StackPanel.DataContext>
                    <local:Student Id="4" Age="18" Name="Jim"></local:Student>
                </StackPanel.DataContext>
                <TextBox Text="{Binding Path=Id}" Margin="5"/>
                <TextBox Text="{Binding Path=Name}" Margin="5"/>
                <TextBox Text="{Binding Path=Age}" Margin="5"/>
            </StackPanel>

6)为列表控件指定ItemsSource

List<Student> stuList = new List<Student>()
            {
                new Student(){ Age = 18, Id = 1, Name = "Xiao"},
                new Student(){ Age = 19, Id = 4, Name = "smao"},
                new Student(){ Age = 20, Id = 3, Name = "duo"},
                new Student(){ Age = 21, Id = 2, Name = "shao"},
            };
            this.listBoxStudents.ItemsSource = stuList;
            this.listBoxStudents.DisplayMemberPath = "Name";
            Binding binding = new Binding("SelectedItem.Id") { Source = this.listBoxStudents };
            this.txtId.SetBinding(TextBox.TextProperty, binding);
            this.listBoxStudents.SelectedIndex = 0;

7)为列表控件指定外衣来绑定集合,绑定的代码是一样的。

<ListBox x:Name="listBoxStudents2" Grid.Row="4">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=Id}" Width="30"/>
                            <TextBlock Text="{Binding Path=Name}" Width="60"/>
                            <TextBlock Text="{Binding Path=Age}" Width="30"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

8)DataTable作为源。

      <StackPanel Grid.Row="1">
                <ListView x:Name="listViewStudents">
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding Path=Id}"/>
                            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Path=Name}"/>
                            <GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding Path=Age}"/>
                        </GridView>
                    </ListView.View>
                </ListView>
            </StackPanel>

this.listViewStudents.ItemsSource = dt.DefaultView;

9)把类的方法包装成数据作为源ObjectDataProvider

ObjectDataProvider odp = new ObjectDataProvider();

odp.ObjectInstance = new Calculator();//方法类

odp.MethodName = "Add"; //方法名

odp.MethodParameters.Add("0"); //添加方法参数

odp.MethodParameters.Add("1");

Binding bindingToArg1 =  new Binding("MethodParameters[0]")

{ Source = odp,    BindsDirectlyToSource = true,

UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };

Binding bindingToArg2 = new Binding("MethodParameters[1]")

{ Source = odp,    BindsDirectlyToSource = true,

UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };

Binding bindingToResult = new Binding(".") { Source = odp };

txtArg1.SetBinding(TextBox.TextProperty, bindingToArg1);//把控件当做目标,源是最终的方法类

txtArg2.SetBinding(TextBox.TextProperty, bindingToArg2);

txtResult.SetBinding(TextBox.TextProperty, bindingToResult);//控件依然是目标,如果是.就是provider的数据

10)自身控件或者上级控件的属性作为源的。

<Grid Grid.Row="2" Grid.Column="2" Background="Black" Margin="15">
            <DockPanel x:Name="Dock" Background="Blue" Margin="20">
                <Grid Background="Orange" Margin="20">
                    <StackPanel>
                        <TextBox Text="{Binding Path=Name, RelativeSource={RelativeSource AncestorLevel=1,AncestorType= {x:Type DockPanel}}}" Margin="0"></TextBox>
                        <TextBox x:Name="txt1" Text="{Binding Path=Name, RelativeSource={RelativeSource Mode=Self}}" Margin="0"></TextBox>
                    </StackPanel>
                </Grid>
            </DockPanel>
        </Grid>

11)使用XML数据作为Binding源。

  12)使用LINQ检索结果作为Binding的源。

  13)binding的数据校验:

private void BindingValidation()
        {
            Binding binding = new Binding("Value") { Source = sliderValidation, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
            RangeValidationRule rvr = new RangeValidationRule();
            rvr.ValidatesOnTargetUpdated = true;
            binding.NotifyOnValidationError = true;
            binding.ValidationRules.Add(rvr);
            this.txtValidation.SetBinding(TextBox.TextProperty, binding);
            this.txtValidation.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));
        }
        private void ValidationError(object sender, RoutedEventArgs e)
        {
            if (Validation.GetErrors(this.txtValidation).Count > 0)
            {
                this.txtValidation.ToolTip = Validation.GetErrors(this.txtValidation)[0].ErrorContent.ToString();
            }
        }

14)binding的转换:

     <ListBox x:Name="listBoxConvert" Grid.ColumnSpan="2">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Width="20" Height="20" Source="{Binding Path=Category,Converter={StaticResource cts}}"></Image>
                            <TextBlock Text="{Binding Path=Name}" Width="60" Margin="80,0"></TextBlock>
                            <CheckBox IsThreeState="True" IsChecked="{Binding Path=State,Converter={StaticResource stnb}}"></CheckBox>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

public class CategoryToSourceConverter : IValueConverter

{

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

Category c = (Category)value;

switch (c)

{

case Category.Bomber:

return @"\Images\Bomber.jpg";

case Category.Fighter:

return @"\Images\Fighter.jpg";

default:                     return null;

}             //throw new NotImplementedException();         }

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{             throw new NotImplementedException();         }

}

public class StateToNullableBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            State s = (State)value;
            switch (s)
            {
                case State.Available:
                    return true;
                case State.Locked:
                    return false;
                default:
                    return null;
            }
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool? nb = (bool?)value;
            switch (nb)
            {
                case true:
                    return State.Available;
                case false:
                    return State.Locked;
                case null:
                default:
                    return State.Unknown;
            }
        }
    }

15)多路binding:

     public void SetMultiBinding()
        {
            Binding b1 = new Binding("Text") { Source = this.txtMult1 };
            Binding b2 = new Binding("Text") { Source = this.txtMult2 };
            Binding b3 = new Binding("Text") { Source = this.txtMult3 };
            Binding b4 = new Binding("Text") { Source = this.txtMult4 };
            MultiBinding mb = new MultiBinding() { Mode = BindingMode.OneWay };
            mb.Bindings.Add(b1);
            mb.Bindings.Add(b2);
            mb.Bindings.Add(b3);
            mb.Bindings.Add(b4);
            mb.Converter = new LogonMultiBindingConverter();
            this.btnSubmit.SetBinding(Button.IsEnabledProperty, mb);
        }

public class LogonMultiBindingConverter : IMultiValueConverter

{

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

if (!values.Cast<string>().Any(text => string.IsNullOrEmpty(text)) &&

values[0].ToString() == values[1].ToString() && values[2].ToString() == values[3].ToString())                   {

return true;

}

return false;

}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)         {             throw new NotImplementedException();         }     }

  16. Binding的BindingMode:

     <Slider x:Name="sliderMode" Grid.Row="1" Grid.ColumnSpan="2" Value="48" Minimum="0" Maximum="100"></Slider>
            <TextBlock Grid.Row="2" Text="OneWay:"></TextBlock>
            <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Value, Mode=OneWay, ElementName=sliderMode}"></TextBox>
            <TextBlock Grid.Row="3" Text="TwoWay:"></TextBlock>
            <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=Value, Mode=TwoWay, ElementName=sliderMode}"></TextBox>
            <TextBlock Grid.Row="4" Text="OneTime:"></TextBlock>
            <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Path=Value, Mode=OneTime, ElementName=sliderMode}"></TextBox>
            <TextBlock Grid.Row="5" Grid.Column="0" Text="OneWayToSource:"></TextBlock>
            <TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Path=Value, Mode=OneWayToSource, ElementName=sliderMode}"></TextBox>
            <TextBlock Grid.Row="6" Text="Default:"></TextBlock>
            <TextBox Grid.Row="6" Grid.Column="1" Text="{Binding Path=Value, Mode=Default, ElementName=sliderMode}"></TextBox>

在讲完binding的使用后,我们接下来深入剖析下binding:

首先看一看binding的一些重要成员:

  binding的源:

    1)RelativeSource。相对资源。 

    2)ElementName:元素名,在指定源的时候,如果是控件,可以指定这个。 

       3)Source:指定binding的源。

4)StaticSource:静态资源. 

  Path: PropertyPath类型,指定源的路径。

  bindingMode:指定绑定的模式。

    1)TwoWay.目标和源都可以影响对方。

    2) OneWay.只有源影响目标。

    3)OneTime.只有程序启动时或者DataContext进行更改时更新目标属性。

    4)OneWayToSource.在目标属性更改时更新源属性。

    5)Default.使用目标属性的默认Mode值。比如TextBox.Text就是双向的,TextBlock.Text就是单向的。

  UpdateSourceTrigger:指定源更新的时期

    1)PropertyChanged. 属性变化的时候更新

    2)LostFocus. 失焦的时候更新。

    3)Explicit.

    4)Default. 缺省。

  NotifyOnSourceUpdated NotifyOnTargetUpdated 这两个Bool属性。

    如果为true表示当源或者目标更新后binding会激发相应的SourceUpdated和TargetUpdated事件。

    实际工作中,我们可以监听这两个事件来找出有哪些数据或者控件被更新了。

ValidationRules.

     ValidationRule的对象集合,这里是指定绑定的验证规则,在进行验证的时候,默认都是认为来自source的数据总是正确的,不需要验证,如果需要验证就要

  设置ValidatesOnTargetUpdated(因为source是会引起Target更新),如果验证的时候的错误需要发出去,需要设置NotifyOnValidationError属性为true,那么

  这个信号就会以binding对象的target为起点在UI树上传播。

Converter.

    数据转换功能,当源与目标的数据类型不一样的时候,就需要使用。需要实现IValueConverter接口,

    其中:

      Convert是转换源到目标。

      ConvertBack:转换目标到源。

到这里为止,我可能还只是对binding的使用有了一个大致的了解,binding与依赖属性,依赖对象之间的关系如何,为什么binding了以后,数据驱动的原理是什么?这些都是一个疑问,我这里只是大致了解了一些类:

Binding是BindingBase的子类。BindingExpression是BindingExpressionBase的子类,BindingOperations是一个静态类。

我这样大致猜想一下:当我们Binding的时候,把源和目标绑定在一起,目标必须是依赖对象,源可以是依赖对象也可以是一般的对象,但必须公开了属性。Binding完成后,如果源是依赖属性或者一般类实现了INotifyPropertyChanged接口,那么肯定就会在弱引用管理器中添加监听者与监听对象,当属性有改变的时候,就会触发相应的事件,使得数据同步得到更新,如果一般的类没有实现这个接口,自然是得不到更新的。

  知道了这些原理,自然就知道了在不同的设置下面源于目标如何发生变化的情况:

  假设源是一个A类对象,其属性P1触发了事件PropertyChanged,P2没有触发事件PropertyChanged,假设分别绑定到了控件C1,C2。

我们来分析一下不同模式下的情况:

  OneWay: P1改变会影响C1,P2改变不会影响C2,C1改变不会影响P1,C2改变不会影响P2。

  TwoWay: P1与C1相互影响,P2与C2互不影响。

  OneTime: P1只会影响C1一次,P2与C2互不影响,C1改变不会影响P1。

  OneWayToSource: P1改变不会影响C1,P2改变不会影响C2,C1改变影响P1,C2改变不会影响P2。

  另外假设源是一个依赖对象,其依赖属性作为路径,那么其在不同模式下的情况就跟上面的假设中P1与C1的情况是一样的。

代码如下

http://files.cnblogs.com/files/monkeyZhong/WPFBindingDemo.zip

    

WPF Binding的更多相关文章

  1. WPF binding 参考

    Introduction This is an article on WPF Binding Cheat Sheet. Some of the Binding won't work for Silve ...

  2. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

  3. WPF Binding值转换器ValueConverter使用简介(二)-IMultiValueConverter

    注: 需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同. 一.MultiBinding+Converter 多值绑定及多值转换实例 当纵向流量大于 ...

  4. WPF Binding值转换器ValueConverter使用简介(一)

    WPF.Silverlight及Windows Phone程序开发中往往需要将绑定的数据进行特定转换,比如DateTime类型的时间转换为yyyyMMdd的日期,再如有一个值是根据另外多组值的不同而异 ...

  5. WPF Binding Mode,UpdateSourceTrigger

    WPF 绑定模式(mode) 枚举值有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWa ...

  6. WPF Binding ElementName方式无效的解决方法--x:Reference绑定

    原文:WPF Binding ElementName方式无效的解决方法--x:Reference绑定 需求: 背景:Grid的有一个TextBlock name:T1和一个ListBox,ListBo ...

  7. UpdateSourceTrigger Property in WPF Binding

    介绍 这篇文章我将介绍在WPF和Silverlight中更新绑定源的概念.正如您所知道的,当我们用TwoWay的模式绑定时,任何在目标控件上发生的变化都会影响绑定源的值. 请注意只是在用TwoWay绑 ...

  8. .NET: WPF Binding对数据的校验和转换以及多路Binding

    一.校验 一般需要对target上的值进行校验. xaml: <Window x:Class="WpfApplication1.MainWindow" xmlns=" ...

  9. WPF Binding学习(二)

    Binding作为数据的桥梁,连通业务逻辑层的对象(源对象)和UI的控件对象(目标对象).在这座桥梁上,我们不仅可以控制在源对象与目标对象是双向通行还是单向通行.还可以控制数据的放行时机,甚至可以在这 ...

随机推荐

  1. iOS 颜色选择器 仿ps 调色板

    前几天写东西,需要到调色板,自己网上搜了一下,好多都写得很麻烦,自己手敲了一个,使用很简单,飞虎不多说,上图,上代码,上使用教程,希望大家喜欢,(基于xcode7.0版本) 最后更新于15/12/14 ...

  2. 以不同用户身份运行程序,/savecred只需要输入一次密码(GetTokenByName取得EXPLORER.EXE的令牌,然后调用CreateProcessAsUser,而且使用LoadUserProfile解决另存文件的问题)good

    http://blog.sina.com.cn/s/blog_65977dde0100s7tm.html ----------------------------------------------- ...

  3. 获得进程可执行文件的路径: GetModuleFileNameEx, GetProcessImageFileName, QueryFullProcessImageName

    http://blog.csdn.net/bichenggui/article/details/4774457 -------------------------------------------- ...

  4. Lua开发环境配置

    Lua(英语发音:/ˈluːə/)程序设计语言是一个简洁.轻量.可扩展的脚本语言,是葡萄牙语中“Luna”(月亮)的意思. Lua is a powerful, fast, lightweight, ...

  5. 【HDOJ】3451 Beat drop

    BFS.当水滴破裂飞溅后,直到碰到水滴才会停止(观察case1).同时,考虑当水滴飞溅到点(x,y)并且该点同一时间破裂的情况,该水滴算作吸收. /* 3451 */ #include <ios ...

  6. 动态规划——F 最大矩阵和

    Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous s ...

  7. JavaScript中的声明提升

    JavaScript中变量或者函数的声明会被提升(赋值语句不会被提升)到当前函数主体的顶部,不管这个声明是否出现在不可到达的地方. var test = 1; function f() { if(!t ...

  8. android图片缓存框架Android-Universal-Image-Loader

    http://blog.csdn.net/king_is_everyone/article/details/34107081 最近跟同学们做了一个创业项目,其实跟以前做项目不同,以前大多数都是做web ...

  9. [yueqian_scut]蓝牙防丢器原理、实现与Android BLE接口编程

    本文是对已实现的蓝牙防丢器项目的总结,阐述蓝牙防丢器的原理.实现与Android客户端的蓝牙BLE接口编程.在这里重点关注如何利用BLE接口来进行工程实现,对于BLE的协议.涉及到JNI的BLE接口内 ...

  10. Where Jboss7.1 take war application to deploy--reference

    Question i've deployed the jboss-as-helloworld-errai application in my standalone jboss7.1 instance, ...