数据模板回顾
在WPF中数据模板可以控制数据的呈现方式。
对于一些简单的数据,例如一个string,一个int,在显示时,无须额外控制 。
但是对于复杂数据类型,就需要使用数据模板来控制数据的呈现方式。
一个简单的例子
假设 我们定义了一个学生类
1 public class Student 2 { 3 public int Id { get; set; } 4 5 public string Name { get; set; } 6 }
然后定义了一个学生列表,并绑定到ListBox
1 var list = new List<Student>(); 2 list.Add(new Student() {Id = 1,Name = "意在" }); 3 list.Add(new Student() { Id = 2, Name = "奎文" }); 4 5 this.list1.ItemsSource = list;
在未使用数据模板前,显示的效果如下:
1 <ListBox Name="list1"></ListBox>
使用了数据模板,显示效果如下:
1 <ListBox Name="list2" Grid.Row="1"> 2 <ListBox.ItemTemplate> 3 <DataTemplate> 4 <WrapPanel> 5 <Label Content="{Binding Id}" FontWeight="Bold" FontSize="20"></Label> 6 <Label Content="{Binding Name}" FontFamily="Arial"></Label> 7 </WrapPanel> 8 </DataTemplate> 9 </ListBox.ItemTemplate> 10 </ListBox>
如何动态创建数据模板
官方的建议是使用 XamlReader.Load 方法从字符串或内存流加载 XAML而不是以编程的方式实现。
这里这两种方式都介绍一下
1、使用XamlReader.Load方法
创建本地XAML文件
1 <DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Grid><Grid.RowDefinitions><RowDefinition /><RowDefinition Height="30" /></Grid.RowDefinitions><Image Source="{Binding ImageUrl}" Width="150" Height="150" /><Label Content="{Binding Title}" FontWeight="Bold" HorizontalAlignment="Center" Grid.Row="1" /></Grid></DataTemplate>
加载XAML文件转换为数据模板并设置到控件上
1 var templateFile = Environment.CurrentDirectory + "\\template.xaml"; 2 var xaml = System.IO.File.ReadAllText(templateFile); 3 using(StringReader sr = new StringReader(xaml)) 4 { 5 XmlReader reader = XmlReader.Create(sr); 6 var template = XamlReader.Load(reader) as DataTemplate; 7 this.listbox.ItemTemplate = template; 8 }
2、使用代码创建数据模板
DataTamplate类可以被实例化,在创建一个DataTamplate对象后,我们需要设置它的VisualTree字段值
VisualTree字段需要的是一个FrameworkElementFactory类型,它可以支持模板创建。
可以看到这个类型的后缀是Factory,所以这里采用了工厂模式,工厂模式是一种常见的设计模式 ,它指的是根据给定的参数动态创建类型,以达到解耦的目的。
还是以上面同样的数据模板进行演示
首先我们创建一个DataTemplate对象
1 DataTemplate template = new DataTemplate();
创建一个Grid
1 FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));
为Grid添加行定义
1 //创建行 2 FrameworkElementFactory row1 = new FrameworkElementFactory(typeof(RowDefinition)); 3 FrameworkElementFactory row2 = new FrameworkElementFactory(typeof(RowDefinition)); 4 row2.SetValue(RowDefinition.HeightProperty, new GridLength(30)); 5 6 //添加行 7 gridFactory.AppendChild(row1); 8 gridFactory.AppendChild(row2);
添加Image控件
1 //添加图像 2 FrameworkElementFactory imageFactory = new FrameworkElementFactory(typeof(Image)); 3 imageFactory.SetValue(Image.SourceProperty, new Binding("ImageUrl")); //Source 4 imageFactory.SetValue(Image.WidthProperty, 150d); //Width 5 imageFactory.SetValue(Image.HeightProperty, 150d); //Height 6 gridFactory.AppendChild(imageFactory);
添加Label控件
1 //添加标题 2 FrameworkElementFactory labelFactory = new FrameworkElementFactory(typeof(Label)); 3 labelFactory.SetValue(Label.ContentProperty, new Binding("Title")); //内容 4 labelFactory.SetValue(Label.FontWeightProperty, FontWeights.Bold); //加粗 5 labelFactory.SetValue(Grid.RowProperty, 1); //Grid.Row = 1 6 labelFactory.SetValue(Label.HorizontalAlignmentProperty, HorizontalAlignment.Center);//HorizontalAlignment 7 gridFactory.AppendChild(labelFactory);
最后将grid设置到DataTemplate的VisualTree上,我们就得到一个动态的数据模板(DataTemplate)对象
1 template.VisualTree = gridFactory;
运行效果
示例代码
github