在WPF中,ObjectDataProvider描述并不多,而且也很难理解。本来对于Binding来说,其Source来源于Resource中定义的一个对象,好比我们在代码中,引用了一个别处定义的一个变量,还是很直观的。可是如果一个Binding的Source是一个ObjectDataProvider的实例的话——无论是来源于DataContext还是在Binding中直接指定,就有点让人蛋疼了。
其实理解ObjectDataProvider还是有窍门的,首先看一个ObjectDataProvider的例子。
public class CDataAccess { ObservableCollection<ImageEmployee> _EmpCollection; public ObservableCollection<ImageEmployee> EmpCollection { get { return _EmpCollection; } set { _EmpCollection = value; } } public CDataAccess() { _EmpCollection = new ObservableCollection<ImageEmployee>(); } public ObservableCollection<ImageEmployee> GetEmployees() { SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=Company;" + "Integrated Security=SSPI"); SqlCommand cmd = new SqlCommand(); conn.Open(); cmd.Connection = conn; cmd.CommandText = "Select * from ImageEmployee"; SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { EmpCollection.Add( new ImageEmployee() { EmpNo = Convert.ToInt32(reader["EmpNo"]), EmpName = reader["EmpName"].ToString(), Salary = Convert.ToInt32(reader["Salary"]), DeptNo = Convert.ToInt32(reader["DeptNo"]), EmpImage = (byte[])reader["EmpImage"] }); } reader.Close(); conn.Close(); return EmpCollection; } } }
<Window x:Class="WPF40_Database.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:WPF40_Database" Title="MainWindow" Height="350" Width="912"> <Window.Resources> <ObjectDataProvider x:Key="objDs" ObjectType="{x:Type data:CDataAccess}" MethodName="GetEmployees"> </ObjectDataProvider> <DataTemplate x:Key="EmpDataTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding EmpName}"></TextBlock> <Image Source="{Binding EmpImage}" Height="60" Width="60"/> </StackPanel> </DataTemplate> </Window.Resources> <Grid DataContext="{Binding Source={StaticResource objDs}}"> <ComboBox Height="80" HorizontalAlignment="Left" Margin="29,30,0,0" Name="lstEmployee" VerticalAlignment="Top" Width="274" ItemsSource="{Binding}" ItemTemplate="{StaticResource EmpDataTemplate}" IsSynchronizedWithCurrentItem="True"/> <TextBox Height="23" HorizontalAlignment="Left" Margin="688,70,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding EmpNo}"/> <TextBox Height="23" HorizontalAlignment="Left" Margin="688,114,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" Text="{Binding EmpName}"/> <TextBox Height="23" HorizontalAlignment="Left" Margin="688,160,0,0" Name="textBox3" VerticalAlignment="Top" Width="120" Text="{Binding Salary}"/> <TextBox Height="23" HorizontalAlignment="Left" Margin="688,204,0,0" Name="textBox4" VerticalAlignment="Top" Width="120" Text="{Binding DeptNo}"/> <Image Height="66" HorizontalAlignment="Left" Margin="688,233,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="120" Source="{Binding EmpImage}"/> <TextBlock Height="23" HorizontalAlignment="Left" Margin="487,70,0,0" Name="textBlock1" Text="EmpNo" VerticalAlignment="Top" Width="169" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="487,117,0,0" Name="textBlock2" Text="EmpName" VerticalAlignment="Top" Width="169" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="487,163,0,0" Name="textBlock3" Text="Salary" VerticalAlignment="Top" Width="169" /> <TextBlock Height="23" HorizontalAlignment="Left" Margin="487,207,0,0" Name="textBlock4" Text="DeptNo" VerticalAlignment="Top" Width="169" /> </Grid> </Window>在这个例子中,
<ObjectDataProvider x:Key="objDs" ObjectType="{x:Type data:CDataAccess}" MethodName="GetEmployees"> </ObjectDataProvider>
这一段就是ObjectDataProvider的典型应用形式,设置了ObjectType、MethodName属性的值;
首先要认识到,WPF在实现中,针对ObjectDataProvider有特别的处理,也就是判断Source如果是DataSourceProvider类型的话——这个类型是ObjectDataProvider的基类,会进行如下的处理,以伪码的形式说明:
if(source is ObjectDataProvider) {
Object instance= 创建ObjectType指定的类型的实例;
使用instance调用MethodName指定的方法,然后返回结果,其实这个结果就是ObjectDataProvider的Data属性;
}
然后把ObjectDataProvider的Data属性作为Binding的真正Source。当然,ObjectDataProvider可以指定构造函数及其参数、指定调用方法的参数,从而更加灵活和强大。