WPF是分离UI和Logic的最佳工具,不同于Window Form的事件驱动原理,WPF采用的是数据驱动,让UI成为了Logic的附属,达到分离的效果。

本篇主要讲讲wpf的精华:data binding

可以把binding看做数据的桥梁,两端分别是source和target,一般来说,source是logic的对象,target是UI的控件对象。

(一)简单的例子

在一个界面里有一个textbox和button,按button后textbox会不停地在Student类的实例的Name属性上增加“Name”,而TextBox显示该实例的Name属性

Student类:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.ComponentModel;

 namespace WpfApplication1
 {
     class Student : INotifyPropertyChanged
     {
         public event PropertyChangedEventHandler PropertyChanged;

         private string name;

         public string Name
         {
             get { return name; }
             set {
                 name = value;
                 if (this.PropertyChanged != null)
                 {
                     this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                 }
             }
         }
     }
 }

MainWindow.xmal:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title=">
     <StackPanel>
         <TextBox x:Name="/>
         <Button Content=" Click="Button_Click"/>
     </StackPanel>
 </Window>

MainWindow.xmal.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         Student stu;
         public MainWindow()
         {
             InitializeComponent();

             stu = new Student();
             Binding binding = new Binding();
             binding.Source = stu;
             binding.Path = new PropertyPath("Name");

             BindingOperations.SetBinding(this.textBoxName, TextBox.TextProperty, binding);
         }

         private void Button_Click(object sender, RoutedEventArgs e)
         {
             stu.Name += "Name";
         }
     }
 }

可以看到在对Student类的Name属性加上PropertyChanged.Invoke函数后就能实现该属性的被绑定了。

MainWindow.xmal只是一个UI,并没有什么Logic部分

而在MainWindow.xmal.cs中,将textBoxName的TextProperty和stu的Name属性进行了绑定,Button_Click事件则只是单单地为Logic了,没有UI的代码,彻彻底底地将UI上数据变化的工作交给了binding自动处理。

从这里可以看出,WPF真的是一个非常牛叉的技术,将UI和Logic完美分离,让UI设计者和业务逻辑者可以并行地开发项目,减少了项目开发时间

当然上面这段代码还可以进行优化

MainWindow.xmal.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         Student stu;
         public MainWindow()
         {
             InitializeComponent();

             this.textBoxName.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu = new Student() });
         }

         private void Button_Click(object sender, RoutedEventArgs e)
         {
             stu.Name += "Name";
         }
     }
 }

(二)控件作为binding source

上面的例子让一个类的属性作为source,通过让类实现INotifyPropertyChanged接口,并在属性的set语句中激发PropertyChanged事件。

除了以类的属性为source外,还有其他的选择,这里先讲第一种:控件作为源

这个时候可以将binding语句放在xaml文件中

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="110" Width="300">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <TextBox x:Name="textBox1" Text="{Binding Path=Value, ElementName=slider1}" BorderBrush="Black" Margin="5" />
         <Slider x:Name="slider1" Maximum="100" Minimum="0" Margin="5" />
     </StackPanel>
 </Window>

这里Text="{Binding Path=Value, ElementName=slider1}"也可以在cs文件里进行绑定

 this.textBox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = "slider1" });

推荐在xaml里进行绑定,控件作为source它不参与logic部分,因此没必要放入cs文件中

为了能够在textBox1里修改数据后slider1能实时更新(默认是要LostFocus才更新),可以这么写

 <TextBox x:Name="textBox1" Text="{Binding Path=Value, ElementName=slider1, UpdateSourceTrigger=PropertyChanged}" BorderBrush="Black" Margin="5" />

Binding的Path其实就是要绑定的source的具体的属性,这里是slider1的Value。如果要显示一个TextBox的文本长度,则Path=Text.Length,如果是TextBox第4个字符,Path=Text[3].

如果Path="."说明source本身就是数据,xaml里可以省略,cs里不行

(三)没有source的binding--使用DataContext作为Binding的源

有的时候binding的path指定了,source并没有指定,则UI元素树会一层一层往上爬,直到有Path指定的属性为止,如果都没有,则什么都没了

为了在xaml能够访问到cs里写的类,需要加上:xmlns:local="clr-namespace:WpfApplication1"。

先在cs里设计student类

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.ComponentModel;

 namespace WpfApplication1
 {
     class Student
     {
         public int Id { get; set; }
         public string Name { get; set; }
         public int Age { get; set; }
     }
 }

再在xaml里创建UI

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication1"
         Title="Simple Binding" Height="150" Width="300">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <StackPanel.DataContext>
             <local:Student Id="6" Age="29" Name="Tim" />
         </StackPanel.DataContext>
         <Grid>
             <StackPanel>
                 <TextBox Text="{Binding Path=Id}" Margin="5" />
                 <TextBox Text="{Binding Path=Name}" Margin="5" />
                 <TextBox Text="{Binding Path=Age}" Margin="5" />
             </StackPanel>
         </Grid>
     </StackPanel>
 </Window>

如果DataContext是<sys:String>Hello DataContext!</sys:String>这种string时,Path=.,也可以将其省略了。

那么问题来了:啥时候用DataContext? 在这个例子中与其这么binding,还不如(一)里面写的改写Student类,而在xaml里进行简单的binding来得简单,而且这里xaml里需要访问cs的类,UI需要知道logic的类设计,对UI设计者来说也增加了负担,似乎不太合理。DataContext在下面两种情况下回用到

1. 当UI上的多个控件都使用Binding关注同一个对象时,不妨使用DataContext。

2. 当作为Source的对象不能被直接访问的时候,比如B窗体内的控件想把A窗体内的控件当做自己的Binding源时,但A窗体内的控件是private访问级别,这时候就可以把这个控件(或者控件的值)作为窗体A的DataContext(这个属性是public访问级别的)从而暴露数据。

形象地说,这时候外层容器的DataContext就相当于一个数据的“制高点”,只要把数据放上去,别的元素就能看见。另外,DataContext本身也是一个依赖属性,我们可以使用Binding把它关联到一个数据源上。

(四)集合对象为source

还是用上面的Student.cs,xaml为:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication1"
         Title="Simple Binding" Height="240" Width="360">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <TextBlock Text="Student ID:" FontWeight="Bold" Margin="5" />
         <TextBox x:Name="textBoxId" Margin="5" />
         <TextBlock Text="Student List:" FontWeight="Bold" Margin="5" />
         <ListBox x:Name="listBoxStudents" Height="110" Margin="5" />
     </StackPanel>
 </Window>

xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();

             List<Student> stuList = new List<Student>()
             {
                 , Name=},
                 , Name=},
                 , Name=},
                 , Name=},
                 , Name=},
                 , Name=},
             };

             this.listBoxStudents.ItemsSource = stuList;
             this.listBoxStudents.DisplayMemberPath = "Name";
             this.textBoxId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.listBoxStudents });
         }
     }
 }

如果想要在listBox里显示Id, Name, Age,则要把this.listBoxStudents.DisplayMemberPath = "Name";得删掉,另外在xaml的listBox里设置它的ItemTemplate为特定的DataTemplate,具体如下

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="240" Width="360">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <TextBlock Text="Student ID:" FontWeight="Bold" Margin="5" />
         <TextBox x:Name="textBoxId" Margin="5" />
         <TextBlock Text="Student List:" FontWeight="Bold" Margin="5" />
         <ListBox x:Name="listBoxStudents" Height="110" Margin="5">
             <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>
     </StackPanel>
 </Window>

(五)ADO.NET对象为source

可以用listBox控件来显示

xaml:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="206" Width="250">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <ListBox x:Name="listBoxStudents" Height="130" Margin="5" />
         <Button Content="Load" Height="25" Margin="5" Click="Button_Click" />
     </StackPanel>
 </Window>

xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }

         private void Button_Click(object sender, RoutedEventArgs e)
         {
             DataTable dt = this.Load();
             this.listBoxStudents.DisplayMemberPath = "Name";
             this.listBoxStudents.ItemsSource = dt.DefaultView;
         }

         private DataTable Load()
         {
             DataTable dt = new DataTable();
             using (MySqlConnection con = new MySqlConnection("server=localhost; database=persons; uid=root; pwd=0000; connect timeout=30; pooling=true"))
             {
                 con.Open();
                 MySqlDataAdapter adapter = new MySqlDataAdapter("SELECT * FROM Student", con);
                 DataSet ds = new DataSet();
                 adapter.Fill(ds, "Student");
                 dt = ds.Tables["Student"];
             }
             return dt;
         }
     }
 }

但是这样显示的内容太少了,多数情况会选择ListView来显示

xaml:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="206" Width="250">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <ListView x:Name="listViewStudents" Height="130" Margin="5">
             <ListView.View>
                 <GridView>
                     <GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding Id}" />
                     <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Name}" />
                     <GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding Age}" />
                 </GridView>
             </ListView.View>
         </ListView>
         <Button Content="Load" Height="25" Margin="5" Click="Button_Click" />
     </StackPanel>
 </Window>

在cs文件里注意将this.listBoxStudents.DisplayMemberPath = "Name";删除,this.listBoxStudents.ItemsSource = dt.DefaultView;改为this.listViewStudents.ItemsSource = dt.DefaultView;

(六)XML为source

先写一个Student.xml文件

 <?xml version="1.0" encoding="utf-8"?>
 <StudentList>
   <Student Id="1">
     <Name>Tim</Name>
   </Student>
   <Student Id="2">
     <Name>Tom</Name>
   </Student>
   <Student Id="3">
     <Name>Vina</Name>
   </Student>
   <Student Id="4">
     <Name>Emily</Name>
   </Student>
 </StudentList>

xaml:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="206" Width="250">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <ListView x:Name="listViewStudents" Height="130" Margin="5">
             <ListView.View>
                 <GridView>
                     <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding XPath=@Id}" />
                     <GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding XPath=Name}" />
                 </GridView>
             </ListView.View>
         </ListView>
         <Button Content="Load" Height="25" Margin="5" Click="Button_Click" />
     </StackPanel>
 </Window>

这里"{Binding XPath=@Id}"的@表示XML元素的Attribute,而没有@说明是子集元素

xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;
 using System.Xml;
 using System.Xml.Linq;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }

         private void Button_Click(object sender, RoutedEventArgs e)
         {
             XmlDataProvider xdp = new XmlDataProvider();
             xdp.Source = new Uri(@"C:\Users\Administrator\Desktop\Demo\Student.XML");
             xdp.XPath = @"/StudentList/Student";
             this.listViewStudents.DataContext = xdp;
             this.listViewStudents.SetBinding(ListView.ItemsSourceProperty, new Binding());
         }
     }
 }

无论是list,还是DataTable,还是XML文件,我们都可以用LINQ技术来写source,这里就不介绍了,具体可以看书

(七)ObjectDataProvider为source

ObjectDataProvider是为第一种情况的补充,因为不能保证每个类的属性都是暴露在外面可以绑定的,有的时候控件上要绑定的值只是一个类的某个方法里的一些参数,这种情况下第一种方法就没用了,而如果重新设计底层类的风险又太大,这个时候用ObejectDataProvider会比较合适。

现在有一个Calculator的类

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace WpfApplication1
 {
     class Calculator
     {
         public string Add(string arg1, string arg2)
         {
             ;
             ;
             ;
             if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
             {
                 z = x + y;
                 return z.ToString();
             }
             return "Input Error!";
         }
     }
 }

在xaml里加个button(这里省略不写了)

在cs里可以先写个简单的objectDataProvider

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;
 using System.Xml;
 using System.Xml.Linq;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }

         private void Button_Click(object sender, RoutedEventArgs e)
         {
             ObjectDataProvider odp = new ObjectDataProvider();
             odp.ObjectInstance = new Calculator();
             odp.MethodName = "Add";
             odp.MethodParameters.Add(");
             odp.MethodParameters.Add(");
             MessageBox.Show(odp.Data.ToString());
         }
     }
 }

这里将对象放在ObjectDataProvider.ObjectInstance属性里,将Method放在ObjectDataProvider.MethodName里,而参数得要用ObjectDataProvider.MethodParameters.Add方法来添加,最后它的结果放在ObjectDataProvider.Data里,这里的参数也可以用data binding的方法。

xaml:

 <Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="Simple Binding" Height="135" Width="300">
     <StackPanel x:Name="stackPanel" Background="LightBlue">
         <TextBox x:Name="textBoxArg1" Margin="5" />
         <TextBox x:Name="textBoxArg2" Margin="5" />
         <TextBox x:Name="textBoxResult" Margin="5" />
     </StackPanel>
 </Window>

cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using System.Data;
 using MySql.Data;
 using MySql.Data.Entity;
 using MySql.Data.MySqlClient;
 using System.Xml;
 using System.Xml.Linq;

 namespace WpfApplication1
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
             this.SetBinding();
         }

         private void SetBinding()
         {
             ObjectDataProvider odp = new ObjectDataProvider();
             odp.ObjectInstance = new Calculator();
             odp.MethodName = "Add";
             odp.MethodParameters.Add(");
             odp.MethodParameters.Add(");

             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
             };

             this.textBoxArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
             this.textBoxArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
             this.textBoxResult.SetBinding(TextBox.TextProperty, new Binding(".") { Source = odp });
         }
     }
 }

这里的odp.MethodParameters.Add("0");不一定是0,可以换成其他数字,区别就在于开始的时候是显示其他数字了。

BindsDirectlyToSource = true这句的意思是告诉Binding对象只负责把从UI元素收集到的数据写入其直接Source(即ObjectDataProvider对象)而不是被ObjectDataProvider对象包装着的Calculator对象。

一般情况下,数据从哪里来哪里就是Binding的source,数据到哪里去哪里就应该是binding的target。按这个理论,前两个textbox应该是ObjectDataProvider对象的数据源,而ObjectDataProvider对象又是最后一个TextBox的数据源。但实际上,三个TextBox都以ObjectDataProvider对象为数据源,只是前两个TextBox在Binding的数据流向上做了限制。这样做的原因不外乎有两个:

1. ObjectDataProvider的MethodParameters不是依赖属性,不能作为Binding的目标。

2. 数据驱动UI的理念要求尽可能地使用数据对象作为Binding的Source而把UI元素当做Binding的Target。

(八)RelativeSource为Source

不能确定Source的对象叫什么名字,但知道它与作为Binding目标的对象在UI布局上有相对关系,比如控件自己关联自己的某个数据,关联自己某级容器的数据,这个时候我们就要使用Binding的RelativeSource属性。这里具体的代码就不写了,可以看书

.NET: WPF Data Binding的更多相关文章

  1. WPF QuickStart系列之数据绑定(Data Binding)

    这篇博客将展示WPF DataBinding的内容. 首先看一下WPF Data Binding的概览, Binding Source可以是任意的CLR对象,或者XML文件等,Binding Targ ...

  2. Data Binding in WPF

    http://msdn.microsoft.com/en-us/magazine/cc163299.aspx#S1   Data Binding in WPF John Papa Code downl ...

  3. [WPF]如何调试Data Binding

    前言 在WPF开发中,将ViewModel中对象绑定到UI上时,会出现明明已经将数据对象Binding到UI,但是UI上就是不显示等等的问题.这篇博客将介绍WPF Data Binding相关的内容, ...

  4. Data Binding和INotifyPropertyChanged是如何协调工作的?

    前言 WPF的一大基础就是Data Binding.在基于MVVM架构的基础上,只有通过实现INotifyPropertyChanged接口的ViewModel才能够用于Data Binding. 要 ...

  5. Optimizing Performance: Data Binding(zz)

    Optimizing Performance: Data Binding .NET Framework 4.5 Other Versions   Windows Presentation Founda ...

  6. WPF binding<一> Data Binding在WPF中的地位

    在代码中看到 <Image Source="{Binding ElementName=LBoxImages, Path=SelectedItem.Source}" /> ...

  7. WPF之数据绑定Data Binding

    一般情况下,应用程序会有三层结构:数据存储层,数据处理层(业务逻辑层),数据展示层(UI界面). WPF是“数据驱动UI”. Binding实现(通过纯C#代码) Binding分为source和ta ...

  8. WPF中的Data Binding调试指南

    大家平时做WPF开发,相信用Visual studio的小伙伴比较多.XAML里面曾经在某些特殊版本的Visual Studio中是可以加断点进行调试的,不过目前多数版本都不支持在XAML加断点来调试 ...

  9. WPF教程三:学习Data Binding把思想由事件驱动转变为数据驱动

    之前大家写代码都喜欢用事件驱动,比如说鼠标输入的click事件.初始化的内容全部放在窗体加载完毕的load事件,等等,里面包含了大量的由事件触发后的业务处理代码.导致了UI和业务逻辑高度耦合在一个地方 ...

随机推荐

  1. java event

    What is an Event? Change in the state of an object is known as event i.e. event describes the change ...

  2. 捕获JS 错误日志

    最近在做项目的过程中,发现很多JS报错没有引起重视,我就想想把JS错误捕获了,然后展示在我们一个平台上 具体实现代码: window.onerror = function(message, url,  ...

  3. 低功耗蓝牙4.0BLE编程-nrf51822开发(9)

    Android 4.3以后的系统自动支持蓝牙4.0规范的低功耗蓝牙(BLE).在android4.3之前,蓝牙4.0支持是由手机厂家加入支持的,接口各异,导致开发一个支持蓝牙4.0程序支持市面上的手机 ...

  4. su terminal get around---docker root

    su : must be run from a terminal After some googling, I found the solution from Tero's glob. If you ...

  5. [LeetCode] Sudoku Solver(迭代)

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  6. LightOj1366 - Pair of Touching Circles(求矩形内圆的对数)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1366 题意:一个H*W的矩形,现在要放入两个外切的圆,问能放多少对这样的圆,其中圆心和 ...

  7. eclipse中hibernate逆向工程出错

    问题已解决!原因是Console configuration的信息编辑有误. 上图中Database connection,如果有已编辑好的可用连接信息就选择,没有的情况下就new一个 如果没有Dri ...

  8. Selenium2学习-032-WebUI自动化实战实例-030-JavaScript 在 Selenium 自动化中的应用实例之五(高亮标示元素)

    在自动化脚本编写过程中,操作元素之前,需要对元素进行高亮显示(通过修改元素的边框样式),同时进行截图,以记录操作的元素对象.在实际应用中较为少见,通常用于演示,或者发生错误时的屏幕截图捕捉,用于错误报 ...

  9. MVC路由约束

    public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/ ...

  10. 30天,O2O速成攻略【8.15长沙站】

    活动概况 时间:2015年08月15日13:30-16:30 地点:库可咖啡(长沙市岳麓区阜埠河路139号天马都乐街,湖南大学天马学生公寓东侧) 主办:APICloud.爱立示.兰软 网址:www.a ...