深入淺出WPF-11.Template(模板)02
模板
DataTemplate和ControlTemplate的關係
通過上面的內容,控制元件只是一個數據和行為的載體,是一個抽象的概念,至於它長什麼樣子,或者它的資料是怎麼展示的,都是由模板生成的。決定控制元件外觀的ControlTemplate,決定資料外觀的是DataTemplate,他們正式Control類的Template和ContentTemplate兩個屬性的值。
凡是Template最終都要作用在控制元件上,這個控制元件就是Template的目標控制元件,也叫模板化控制元件。DataTemplate給人的感覺是施加在資料物件上,但是施加在資料物件上生成的一組控制元件總要有一個載體,這個載體就是ContentPresenter物件。ContentPresenter物件只有ContentTemplate屬性,沒有Template屬性,這就證明了承載由DataTemplate生成的一組控制元件的專門用途。
由ControlTemplate生成的控制元件樹其樹根就是ControlTemplate的目標控制元件,此模板化控制元件的Template屬性值就是這個ControlTemplate例項;與之相仿,有DataTemplate生成的控制元件樹其樹根是一個ContentPresenter控制元件,此模板化控制元件的ContentTemplate屬性值就是這個DataTemplate例項。因為ContentPresenter控制元件是ControlTemplate控制元件樹上的一個結點,所以DataTemplate控制元件樹是ControlTemplate控制元件樹的一顆子樹。
DataTemplate和ControlTemplate的繫結
每個控制元件都有一個名為TemplatedParent的屬性,如果他的值不為null,說明這個控制元件是由Template自動生成的,而屬性值就是應用了模板的控制元件。如果由Template生成的控制元件使用了TemplateBinding獲取屬性值,則TemplateBinding的資料來源就是應用了這個模板的目標控制元件。
如果使用了普通繫結Binding而不是TemplateBinding,那麼資料來源就是Source,如果不指定的話,Binding就會沿著邏輯樹一直向上找,查詢每個結點的DataContext屬性,如果DataContext引用的物件具有Path指定的屬性名,Binding就會把這個物件當做自己的資料來源。顯然,如果把資料物件賦值給ContentPresenter的DataContext屬性,有DataTemplate生成的控制元件自然會找這個資料物件作為自己的資料來源。
簡單的理解為:控制元件模板ControlTemplate中的改變的是控制元件的外形,使用的一般是TemplateBinding,對應的資料來源是應用這個這個ControlTemplate的目標控制元件。DataTemplate資料模板改變的是資料的展示形式,一般是普通的Binding,資料來源是需要展示的資料內容。
<DataTemplate x:Key="ListBoxItemOCTDataTemplate" DataType="{x:Type ListBoxItem}">
<Border Margin="0">
<Grid Width="{StaticResource ListBoxOCTWidth}" Height="{StaticResource ListBoxOCTHeight}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<TextBlock
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{StaticResource CommonForeground}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SnapsToDevicePixels="True"
Text="{Binding ImageLaterality, Converter={StaticResource ListBoxEyeStringConverter}}"
TextWrapping="NoWrap" />
<TextBlock
Margin="0,0,8,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="14"
Foreground="{StaticResource CommonForeground}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SnapsToDevicePixels="True"
Text="{Binding CreationDateTime}"
TextWrapping="NoWrap" />
</Grid>
<Grid Margin="2,2,2,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="4" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ImageJpgThumbPathBitmap}" />
<Image Grid.Column="2" Source="{Binding OCTJpgThumbPathBitmap}" />
</Grid>
<Grid Margin="2,2,2,2">
<Image Source="{Binding VideoFileFullPathBitmap}" />
</Grid>
<Grid Grid.Row="2">
<TextBlock
Margin="8,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Foreground="{StaticResource CommonForeground}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SnapsToDevicePixels="True"
Text="{Binding ScanDataTypeRemark}"
TextWrapping="NoWrap" />
</Grid>
</Grid>
</Border>
</DataTemplate>
這裡,切記一點控制元件的Template屬性和ContentTemplate屬性是兩個完全不一樣的,Template屬性的值是ControlTemplate,而ContentTemplate的值是DataTemplate。