在现代的UI开发中,经常需要根据不同的数据类型来展示不同的视图。Silverlight5 Beta引入了一个名为“隐式数据模板”的新特性,它允许为同一个控件声明多个数据模板,并根据数据类型自动加载合适的数据模板。本文将通过一个简单的例子,逐步介绍如何使用这一特性。
目标分析
假设有一个组织,其中包含员工和客户两种角色。需要存储这两种人的记录,并以合适的方式展示这些记录。为了演示隐式数据模板的使用,将创建一个ListBox,并在其中区分人员是员工还是客户。
环境准备
在开始之前,需要设置好开发环境。需要安装Visual Studio 2010 SP1和Silverlight5 Beta Tools for Visual Studio 2010。然后,创建一个新的Silverlight项目。
解决方案设置
在开始编写代码之前,需要以MVVM的方式设置解决方案。首先,在解决方案资源管理器中创建目录结构。对于MVVM示例,将创建"Models"、"Views"、"ViewModels"和"Services"文件夹。
接下来,在适当的位置创建类和XAML。在"Views"文件夹中添加MainView.xaml,在"ViewModels"文件夹中添加MainViewModel.cs,在"Services"文件夹中添加DataService.cs,并在"Models"文件夹中添加一个名为IPerson.cs的接口。然后在同一个"Models"文件夹中创建两个类Customer.cs和Employee.cs,并实现IPerson接口。
接口实现
在接口中声明一些属性,如FirstName、LastName和Age。
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
int Age { get; set; }
}
模型实现
一旦接口准备好,就可以在契约类中实现接口属性。
public class Employee : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class Customer : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
实现DataService
需要一个DataService来返回Person的详细信息。Person可以是Employee或Customer。假设从数据库中获取这些信息并返回给客户端。在这里,将硬编码集合并返回它。
public class DataService
{
public ObservableCollection<IPerson> GetPersons()
{
List<IPerson> persons = new List<IPerson>
{
new Employee { FirstName = "John", LastName = "Doe", Age = 30 },
new Customer { FirstName = "Jane", LastName = "Doe", Age = 25 }
};
return new ObservableCollection<IPerson>(persons);
}
}
实现ViewModel
接下来,开始编写ViewModel。实现INotifyPropertyChanged接口,以便在属性更改时自动通知视图进行刷新。然后创建一个名为Persons的属性,类型为ObservableCollection<IPerson>。
public class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<IPerson> Persons { get; private set; }
public MainViewModel()
{
DataService service = new DataService();
Persons = service.GetPersons();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
视图实现
现在来创建视图并将集合绑定到ListBox。首先,添加Model和ViewModel的命名空间。然后,在UserControl.Resources中添加MainViewModel作为StaticResource。
<UserControl.Resources>
<local:MainViewModel x:Key="MainViewModel" />
</UserControl.Resources>
添加一个ListBox并将DataContext设置为MainViewModel实例。同时,将ListBox的ItemsSource属性绑定到MainViewModel中的Persons集合。
<ListBox x:Name="PersonListBox" ItemsSource="{Binding Persons}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName} {Binding LastName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
创建隐式数据类型
使用隐式数据类型,可以为单个控件实例使用多个数据模板,并根据数据相应地显示数据。将使用之前示例中相同的DataTemplate。
<ListBox x:Name="PersonListBox" ItemsSource="{Binding Persons}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Employee}">
<TextBlock Text="{Binding FirstName} {Binding LastName} - Employee" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Customer}">
<TextBlock Text="{Binding FirstName} {Binding LastName} - Customer" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
演示
现在可以在应用程序中看到效果了。将注意到它为正确的数据类型使用了正确的DataTemplate。检查从DataService收到的集合,并与UI中的数据进行匹配。会发现它们是相似的。