1. 程式人生 > 實用技巧 >深入淺出WPF-11.Template(模板)02

深入淺出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。