WPF中如何使用后台代码动态创建数据模板(DataTemplate)

数据模板回顾 

在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设置到DataTemplateVisualTree上,我们就得到一个动态的数据模板(DataTemplate)对象

1  template.VisualTree = gridFactory;

 

运行效果

 

示例代码

github

posted @   zhaotianff  阅读(191)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
历史上的今天:
2021-08-22 如何知道安装程序在进行安装时对你的电脑到底做了什么?
2021-08-22 架构师笔记:康威定律
点击右上角即可分享
微信分享提示