[UWP]如何使用代碼創建DataTemplate(或者ControlTemplate)


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM