I. Binding to Object
1. Binding data using ObjectDataProvider
AC:Let’s say there is a CLR based data bound object that you are trying to implement. For example a collection of Tool objects, e.g.
- An Object called Tool that contains a bunch of properties that we want to bind (in this case it just contains a description)
- A Collection of Tool objects( ToolsCollection ); for example to populate a list box etc
- A Factory to get the reference of ToolsCollection objects which have collection<Tools>
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CLRDataBinding { public class Tool : INotifyPropertyChanged { private string _description = "" ; public string Description { get { return _description; } set { if (_description != value) { _description = value; NotifyPropertyChanged( " Description " ); } } } public Tool( string description) { _description = description; } public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged( string propName) { if (PropertyChanged != null ) { PropertyChanged( this , new PropertyChangedEventArgs(propName)); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.ObjectModel; namespace CLRDataBinding { public class ToolsCollection : ObservableCollection<Tool> { public ToolsCollection() { CreateToolsData(); } private void CreateToolsData() { for ( int loop = 0 ; loop < 1000 ; loop++ ) { this .Add( new Tool( " Tool " + loop.ToString())); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CLRDataBinding { public class Factory { public ToolsCollection MyToolsCollection { get { return new ToolsCollection(); } } } }
< Window x:Class ="CLRDataBinding.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:clr ="clr-namespace:CLRDataBinding" Title ="MainWindow" Width ="525" Height ="350" > < Window.Resources > < ObjectDataProvider x:Key ="FactoryDP" ObjectType =" {x:Type clr:Factory} " /> < DataTemplate x:Key ="ToolItemTemplate" > < StackPanel > < TextBlock Text =" {Binding Description} " /> </ StackPanel > </ DataTemplate > </ Window.Resources > < Grid > < ListBox ItemTemplate =" {StaticResource ToolItemTemplate} " ItemsSource =" {Binding Path=MyToolsCollection, Source={StaticResource FactoryDP}} " /> </ Grid > </ Window >
之前一篇文章 对象数据绑定 里提到三个例子,第一个例子用了ObjectDataProvider没有用DataContext,第二个例子用了DataContext没有用 ObjectDataProvider,第三个例子既用了ObjectDataProvider也用了DataContext,但没有提到它们的区别,正 好在Beatriz Costa的blog上看到一篇好文章解释了为 什么需要 ObjectDataProvider 的问题。
ObjectDataProvider能实现四个特殊功能:
1. 传递参数到构造函数中
使用下面的XAML语句定义一个ObjectDataProvider,它会自动调用MySource类的默认构造函数初始化类
<ObjectDataProvider ObjectType="{x:Type local:MySource}" x:Key="odp1"/>
如果MySource类的构造函数允许传入参数的话,就可以这样定义ObjectDataProvider:
<ObjectDataProvider ObjectType="{x:Type local:MySource}" x:Key="odp1">
<ObjectDataProvider.ConstructorParameters>
<system:String>Jupiter</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
2. 绑定到方法
ObjectDataProvider 除了 ObjectType的属性外还有MethodName的属性,MethodName属性将ObjectDataProvider绑定到方法,相当于是对数据源的包装,另外也可以定义方法的传入参数:
<ObjectDataProvider ObjectInstance="{StaticResource odp1}" MethodName="WeightOnPlanet" x:Key="odp2">
<ObjectDataProvider.MethodParameters>
<system:Double>95</system:Double>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
3. 替换数据对象
和使用自己在resource中定义对象不同,ObjectDataProvider可以使里很简单的更换绑定的数据对象,只需要更换一下绑定的数据对象的名字。而使用自己在resource中定义对象,即使定义了相同的x:Key也不能达到自动更新的目的。
另,这里使用DataContext也能达到与ObjectDataProvider同样的效果。
4. 建立异步的数据对象
ObjectDataProvider有IsAsynchronous 可以将数据对象定义为异步的。
默认情况下ObjectDataProvider是同步的,XmlDataProvider是异步。
2. Binding DataContext in Window.DataContext (ObjectDataProvider not needed)
AuctionItem.cs: define
Class
AuctionItem
:
INotifyPropertyChanged
MyApp.xaml.cs: define
Class
AuctionItems
:
ObservableCollection<AuctionItem>
Window1.xaml.cs: use [CollectionViewSource cv = root.DataContext as CollectionViewSource;] to action in button event handler
Binding Process:
1)Define DataContext in Window1.xaml:
< Window.DataContext > < CollectionViewSource > < CollectionViewSource.Source > < local:AuctionItems /> </ CollectionViewSource.Source > </ CollectionViewSource > </ Window.DataContext >
2) Binding Listbox:
< ListBox ItemsSource =" {Binding Path=.} " IsSynchronizedWithCurrentItem ="True" >
3) Binding label: (the current item in listbox)
< Label Content =" {Binding Path=/} " >
4) DataTemplate
< DataTemplate DataType =" {x:Type local:AuctionItem} " > ... < Image > < Image.Source > < Binding Path ="Image" /> </ Image.Source > </ Image > ...
More: this sample also shows how to use Converter and MultiBinding
3. Binding DataContext in controls to Global ObjectDataProvider
sample:
MyApp.xaml:
< Application.Resources > ... < ObjectDataProvider x:Key ="Employees" ObjectType =" {x:Type local:MSEmployeeCollection} " /> </ Application.Resources >
Window1.xaml:
< StackPanel Margin ="10" DataContext =" {StaticResource Employees} " > ... < Button Content =" {Binding Path=[0]} " /> < ComboBox ItemsSource =" {Binding} " SelectedIndex ="0" /> </ StackPanel >
1) DataContext another format : binding to StackPanel
2) Button bind to single item [0]
3) ComblBox bind to multi items, so no Path
II. Binding to XML
1. Use Source include .xml file to XmlDataProvider
<? xml version='1.0' encoding='utf-8' ?> < StackPanel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" Margin ="10" > < StackPanel.Resources > < XmlDataProvider x:Key ="Blog" Source ="http://home.wangjianshuo.com/index.xml" /> < DataTemplate x:Key ="TitleTemplate" > < TextBlock Text =" {Binding XPath=title} " /> </ DataTemplate > </ StackPanel.Resources > < Label Content =" {Binding Source={StaticResource Blog}, XPath=/rss/channel/title} " FontSize ="24" FontWeight ="Bold" /> < Label Content =" {Binding Source={StaticResource Blog}, XPath=/rss/channel/description} " FontSize ="18" /> < DockPanel DataContext =" {Binding Source={StaticResource Blog}, XPath=/rss/channel/item} " > < ListBox DockPanel.Dock ="Left" ItemsSource =" {Binding} " ItemTemplate =" {StaticResource TitleTemplate} " IsSynchronizedWithCurrentItem ="True" /> < TextBox Name ="Contents" Text =" {Binding XPath=description} " TextWrapping ="Wrap" Width ="Auto" /> </ DockPanel > </ StackPanel >
2. Use x:XData define the xml structure inside current XmlDataProvider
< StackPanel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" > < StackPanel.Resources > < XmlDataProvider x:Key ="FavoriteColors" > < x:XData > < Colors xmlns ="" > < Color > Blue </ Color > < Color > Black </ Color > < Color > Green </ Color > < Color > Red </ Color > </ Colors > </ x:XData > </ XmlDataProvider > </ StackPanel.Resources > < TextBlock HorizontalAlignment ="Center" FontWeight ="Bold" > XML Example </ TextBlock > < ListBox Width ="200" Height ="300" ItemsSource =" {Binding Source={StaticResource FavoriteColors}, XPath=/Colors/Color} " > </ ListBox > </ StackPanel >
III. Binding to Control
1:
< Window xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" > < Canvas > < TextBox Name ="theTextBox" Text ="Hello" /> < TextBlock Canvas.Top ="25" > < TextBlock.Text > < Binding ElementName ="theTextBox" Path ="Text" /> </ TextBlock.Text > </ TextBlock > </ Canvas > </ Window >
2:
< Window xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" > < Canvas > < TextBox Name ="theTextBox" Text ="Hello" /> < TextBlock Canvas.Top ="25" Text =" {Binding ElementName=theTextBox, Path=Text} " /> </ Canvas > </ Window >
IX. Binding to ADO.NET
Similar to binding to object, create a dataset and return ds to DataContext.