WPF中控制模板和数据模板的区别

227

在WPF中,ControlTemplateDataTemplate有什么区别?

7个回答

300
通常,控件是为了本身而呈现的,并不反映底层数据。例如,一个Button并不会绑定到业务对象——它只是为了能够被点击而出现。然而,ContentControlListBox通常会出现,以便为用户呈现数据。
因此,DataTemplate用于为底层数据提供视觉结构,而ControlTemplate与底层数据无关,仅为控件本身提供视觉布局。 ControlTemplate通常只包含TemplateBinding表达式,将其绑定回控件本身的属性,而DataTemplate将包含标准的绑定表达式,将其绑定到其DataContext(业务/域对象或视图模型)的属性。

30
听起来有道理吗?我想我试图解释哲学上的差异而不是技术上的差异。 - Matt Hamilton

126

简单来说,ControlTemplate 描述如何显示一个控件,而 DataTemplate 描述如何显示数据。

例如:

Label 是一个控件,它包含一个 ControlTemplate,该模板指定了应该使用一个围绕某些内容(DataTemplate 或另一个控件)的 Border 来显示这个 Label

Customer 类是数据,并且将使用一个 DataTemplate 来显示。该模板可以指定将 Customer 类型显示为一个包含两个 TextBlocksStackPanel,其中一个显示姓名,另一个显示电话号码。值得注意的是,所有类都使用 DataTemplates 显示,通常会使用默认模板,即一个带有对象的 ToString 方法返回值的 TextBlock


因为描述简洁易懂,所以我点了赞。非常感谢。 - Pete Magsig

35

Troels LarsenMSDN论坛上有一个很好的解释。

<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>

(模板明显是从http://msdn.microsoft.com/en-us/library/system.windows.controls.controltemplate.aspxhttp://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplate%28VS.95%29.aspx中抄袭的)

无论如何,ControlTemplate决定了按钮本身的外观,而ContentTemplate决定了按钮内容的外观。因此,您可以将内容绑定到您的数据类之一,并使其以任何您想要的方式呈现。


25

ControlTemplate: 表示控件的样式。

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

所有控件都使用默认的控件模板,您可以通过模板属性覆盖它。

例如
Button 模板是控件模板。 Button 内容模板是数据模板。

<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");
    }
}

10

ControlTemplate - 改变元素的外观。例如,Button 可以包含图像和文本。

DataTemplate - 使用元素表示底层数据。


2

ControlTemplate 定义了控件的视觉外观,DataTemplate 替换数据项的视觉外观。

例如:我想将按钮从矩形变为圆形 => 使用 Control Template。

如果您有复杂的对象传递给控件,它只会调用并显示 ToString() 方法,而使用 DataTemplate 可以获取数据对象的各种成员并显示和更改它们的值。


2
所有以上的答案都很好,但是有一个被忽略的关键区别。这有助于更好地决定何时使用什么。它是ItemTemplate属性:
  • DataTemplate用于提供为您提供ItemTemplate属性的元素,以便您根据之前定义的DataTemplate和通过您提供的选择器绑定数据来替换其项的内容。

  • 但是,如果您的控件没有为您提供此功能,则仍然可以使用ContentView,该控件可以从预定义的ControlTemplate中显示其内容。有趣的是,您可以在运行时更改ContentViewControlTemplate属性。还有一件需要注意的事情是,与具有ItemTemplate属性的控件不同,您无法为此(ContentView)控件创建TemplateSelector。但是,您仍然可以创建触发器以在运行时更改ControlTemplate


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接