1. 前言 在UWP中DataTemplate是一個十分重要的功能,並且幾乎無處不在,例如DataGrid中的DataGridTemplateColumn: 而且DateTemplate(或ControlTemplate)極有可能需要由代碼動態生成。 UWP大致上有兩種使用代碼生成DateTempl ...
1. 前言
在UWP中DataTemplate是一個十分重要的功能,並且幾乎無處不在,例如DataGrid中的DataGridTemplateColumn:
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="{x:Bind FirstName}" />
<TextBlock Text="{x:Bind LastName}" />
</StackPanel>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
而且DateTemplate(或ControlTemplate)極有可能需要由代碼動態生成。
UWP大致上有兩種使用代碼生成DateTemplate的方式。
2. 使用資源字典
這其實並不是由代碼動態生成DataTemplate,只是比較方便的從資源字典讀取DataTemplate的邪道,一般來說不好意思暴露給項目外的用戶。
創建一個UserControl,然後把父類從“UserControl”改為“ResourceDictionary”,然後在Xaml中編寫DataTemplate,為這個DataTemplate的x:Name賦值,並且將x:FieldModifier改為“internal”(這樣DataTemplate才可以作為一個欄位被項目中的其它類訪問),代碼如下:
public sealed partial class XamlResource : ResourceDictionary
{
public XamlResource()
{
this.InitializeComponent();
}
}
<ResourceDictionary x:Class="App5.XamlResource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App5"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<DataTemplate x:Name="ItemTemplate"
x:FieldModifier="internal" >
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ResourceDictionary>
使用起來也很方便:
XamlResource resource = new XamlResource();
ListControl.ItemTemplate = resource.ItemTemplate;
這種做法的好處是編輯Datatemplate時有智能感知和屬性面板,不容易出錯;調用起來也很簡單。雖然不夠動態,但我常常使用這種方式創建DataTemplate。
3. 使用XamlReader
XamlReader用於解析XAML並創建相應的對象樹。文檔里給出的例子是構建一個Ellipse:
string xaml ="<Ellipse Name=\"EllipseAdded\" Width=\"300.5\" Height=\"200\" Fill =\"Red\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>";
object ellipse = XamlReader.Load(xaml);
當然了,要在代碼里構建一個Ellipse何必這樣大費周章。對於XamlReader,我平時用得最多的就是用來創建DataTemplate和ControlTemplate這些不方便用代碼構建的元素。記得在XAML的根元素添加xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
和xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
:
var template = (DataTemplate)XamlReader.Load(@"
<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<TextBlock Text=""{Binding " + DisplayMemberPath + @"}"" VerticalAlignment=""Center""/>
</DataTemplate>");
ListControl.ItemTemplate = template;
這種方式滿足了“動態”這個需求,缺點也很明顯:動態的就容易出錯,而且這種方式很難構建複雜的DataTemplate。
4. 結語
這兩種方式我都很常用,複雜的就用資源字典方式,簡單但需要動態的就用XamlReader。有些人會為XamlReader做得更多,例如通過反射將一個TextBlock轉換為XAML,再使用XamlReader讀取成DataTemplate。我覺得這樣也不錯,但我還沒遇到過這種應用場景就不嘗試了。
5. 參考
DataTemplate
XamlReader
x:FieldModifier