在WPF中控制模板和数据模板之间的区别是什么?


当前回答

以上所有的答案都很棒,但有一个关键的区别被忽略了。这有助于更好地决定何时使用什么。它是ItemTemplate属性:

DataTemplate is used for elements that provide ItemTemplate property for you to replace its items' content using DataTemplates you define previously according to bound data through a selector that you provide. But if your control does not provide this luxury for you then you still can use a ContentView that can display its content from predefined ControlTemplate. Interestingly, you can change the ControlTemplate property of your ContentView at runtime. One more thing to note that unlike controls with ItemTemplate property, you cannot have a TemplateSelector for this (ContentView) control. However, you still can create triggers to change the ControlTemplate at runtime.

其他回答

以上所有的答案都很棒,但有一个关键的区别被忽略了。这有助于更好地决定何时使用什么。它是ItemTemplate属性:

DataTemplate is used for elements that provide ItemTemplate property for you to replace its items' content using DataTemplates you define previously according to bound data through a selector that you provide. But if your control does not provide this luxury for you then you still can use a ContentView that can display its content from predefined ControlTemplate. Interestingly, you can change the ControlTemplate property of your ContentView at runtime. One more thing to note that unlike controls with ItemTemplate property, you cannot have a TemplateSelector for this (ContentView) control. However, you still can create triggers to change the ControlTemplate at runtime.

Troels Larsen在MSDN论坛上有很好的解释

<Window x:Class="WpfApplication7.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <DataTemplate x:Key="ButtonContentTemplate"> <StackPanel Orientation="Horizontal"> <Grid Height="8" Width="8"> <Path HorizontalAlignment="Stretch" Margin="0,0,1.8,1.8" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000" Data="M0.5,5.7 L0.5,0.5 L5.7,0.5"/> <Path HorizontalAlignment="Stretch" Margin="2,3,0,0" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF" Data="M3.2,7.5 L7.5,7.5 L7.5,3.5"/> <Path HorizontalAlignment="Stretch" Margin="1.2,1.4,0.7,0.7" VerticalAlignment="Stretch" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M2.5,2.5 L7.5,7.5"/> <Path HorizontalAlignment="Stretch" Margin="1.7,2.0,1,1" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000" Data="M3,7.5 L7.5,7.5 L7.5,3.5"/> <Path HorizontalAlignment="Stretch" Margin="1,1,1,1" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF" Data="M1.5,6.5 L1.5,1 L6.5,1.5"/> </Grid> <ContentPresenter Content="{Binding}"/> </StackPanel> </DataTemplate> <ControlTemplate TargetType="Button" x:Key="ButtonControlTemplate"> <Grid> <Ellipse Fill="{TemplateBinding Background}"/> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Window.Resources> <StackPanel> <Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="1"/> <Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="2"/> <Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="3"/> </StackPanel> </Window> (Templates blatently stolen from http://msdn.microsoft.com/en-us/library/system.windows.controls.controltemplate.aspx and http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplate%28VS.95%29.aspx respectively) Anyway, the ControlTemplate decides how the Button itself looks, while the ContentTemplate decides how the Content of the button looks. So you could bind the content to one of you data classes and have it present itself however you wanted it.

通常情况下,控件是为其本身而呈现的,并不反映底层数据。例如,一个Button不会被绑定到业务对象上——它的存在纯粹是为了可以被点击。然而,ContentControl或ListBox通常出现,以便为用户显示数据。

因此,DataTemplate用于为底层数据提供可视化结构,而ControlTemplate与底层数据无关,只是为控件本身提供可视化布局。

一个ControlTemplate通常只包含TemplateBinding表达式,绑定回控件本身的属性,而一个DataTemplate将包含标准binding表达式,绑定到它的DataContext(业务/域对象或视图模型)的属性。

ControlTemplate:表示控件样式。

DataTemplate:表示数据样式(您希望如何显示数据)。

所有控件都使用可以通过template属性重写的默认控件模板。

例如 按钮模板是控件模板。 按钮内容模板是一个数据模板

<Button   VerticalAlignment="Top" >
    <Button.Template>
        <ControlTemplate >
            <Grid>
                <Rectangle Fill="Blue" RadiusX="20" RadiusY="20"/>
                <Ellipse Fill="Red" />
                <ContentPresenter Content="{Binding}">
                    <ContentPresenter.ContentTemplate>
                        <DataTemplate>
                        <StackPanel Orientation="Horizontal" Height="50">
                            <TextBlock Text="Name" Margin="5"/>
                                <TextBox Text="{Binding UserName, Mode=TwoWay}" Margin="5" Width="100"/>
                            <Button Content="Show Name" Click="OnClickShowName" />
                        </StackPanel>
                    </DataTemplate>
                    </ContentPresenter.ContentTemplate>
                </ContentPresenter>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

public String UserName
{
    get { return userName; }
    set
    {
        userName = value;
        this.NotifyPropertyChanged("UserName");
    }
}

ControlTemplate定义视觉外观,dattemplate替换数据项的视觉外观。

示例:我想显示一个按钮从矩形到圆形的形式=>控制模板。

如果控件有复杂的对象,它只调用并显示ToString(),使用DataTemplate,您可以获得各种成员并显示和更改数据对象的值。