.net 什么';ContentControl和ContentPresenter之间的区别是什么?

.net 什么';ContentControl和ContentPresenter之间的区别是什么?,.net,wpf,contentcontrol,contentpresenter,.net,Wpf,Contentcontrol,Contentpresenter,我不确定什么时候应该使用ContentPresenter而不是ContentControl(反之亦然)。目前,我在DataTemplates中几乎一直在使用ContentControl。什么时候ContentPresenter会是一个更好的选择?为什么?ContentPresenter通常在ControlTemplate中用作占位符,表示“将实际内容放在此处” ContentControl可以在任何地方使用,不一定在模板中使用。它将拾取为分配给它的内容类型定义的任何数据模板。控件是包含其他元素且

我不确定什么时候应该使用
ContentPresenter
而不是
ContentControl
(反之亦然)。目前,我在
DataTemplate
s中几乎一直在使用
ContentControl
。什么时候
ContentPresenter
会是一个更好的选择?为什么?

ContentPresenter通常在ControlTemplate中用作占位符,表示“将实际内容放在此处”


ContentControl可以在任何地方使用,不一定在模板中使用。它将拾取为分配给它的内容类型定义的任何数据模板。控件是包含其他元素且具有
内容
-属性(例如,
按钮
)的控件的基类

ContentPresenter
在控件模板中用于显示内容


ContentControl
直接使用时(它应该用作基类),有一个使用ContentPresenter显示其内容的控件模板

我的经验法则(并非适用于所有情况,请根据您的判断):

  • 内部
    ControlTemplate
    使用
    ContentPresenter
  • ControlTemplate
    之外(包括
    DataTemplate
    和外部模板),尽量不要使用任何一种模板,如果需要,您必须选择
    ContentPresenter
  • 子类
    ContentControl
    如果要创建承载内容的自定义“lookless”控件,并且无法通过更改现有控件的模板获得相同的结果(这应该非常罕见)

  • 我最近在我的博客上写了一篇关于这两个控件的帖子:

    ContentPresenter.ContentSource实际上是这两个类之间最大的区别。 ContentSource属性仅在ControlTemplate中有意义;它确定内容应该映射到哪个TemplatedParent属性。 例如,如果控件包含一个依赖属性
    MyProperty1
    ,那么我们可能会在其
    控件模板中找到以下内容:

    <ControlTemplate TargetType="MyControl" >
        [...]
           <ContentPresenter ContentSource="MyProperty1" />
        [...]
    </ControlTemplate>
    
    
    [...]
    [...]
    
    ContentPresenter的内容将收到
    MyProperty1
    的值

    请注意,如果属性名称为
    Content
    ,则无需指定
    ContentSource
    ,因为它是默认值


    对于那些知道angularJs的人来说:这类似于《排除麦加主义》。

    有时候一个例子比理论术语更容易。在MS网站(滚动至底部:)中,它使用按钮作为示例。按钮有一个ContentControl,它允许您放置一个控件或自定义控件,可以是图像、文本、复选框、堆栈面板、网格等

    自定义按钮之后,现在在Xaml上,您可以编写

    <my:Button>
       <my:Button.Content>
          <my:AnotherControl>
       </my:Button.Content>
    </my:Button>
    
    
    
    在上面的示例代码中,“my:Button.Content”是ContentControl。另一个控件将放置在您指定的ContentPresenter所在的位置


    类似地,当比较TextBox和TextBlock时,TextBox有一个ContentPresenter供您在其中填充内容,就像上面的按钮示例一样,而TextBlock没有。文本块仅允许您输入文本

    这是一个老问题,但我刚刚完成为通用应用程序开发一个基于模板的动画平铺控件,请看旧手机WP7/8 SDK中的以下代码:

    <ContentControl x:Name="contentControl" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch">
        <ContentPresenter x:Name="contentPresenter" CacheMode="BitmapCache"/>
    </ContentControl>
    
    
    

    在这里可以看到ContentControl是用于显示内容的容器和演示者。在大多数情况下,ControlTemplate将是一个容器,但如果您希望在
    ControlTemplate
    另一个容器中放置一个额外的容器:
    ContentControl
    ,并使用一个单独的
    ContentPresenter
    来呈现内容。如果您不需要单独的容器,那么只需使用
    ControlTemplate
    ControlPresenters
    来显示内容块,至少这是微软开发WP7/8SDK时所做的。ContentControl也可以用于显示内容,但它同时充当容器和演示者。因此,在上面的示例代码中,它的用途在容器和演示器中分开。在动态示例中,您可以显示容器(它可以有空的背景或还没有的内容),然后动态地用presenter内容填充它。容器具有尺寸(宽度、高度等),您可以将这些属性放在容器控件上并在其上显示内容。在示例中,ContentControl确定了如何处理presenter内容。

    ContentPresenter不也会导致对其内容应用DataTemplate吗?这不是它的主要目的之一吗?嗯。。。是的,可能。不管怎样,Bea Stollnitz的解释比我的好得多;)你简洁的回答似乎很快就概括了这一点:我相信ContentPresenter的整个设计就是简单地“实现”DataTemplate膨胀——它似乎唯一的任务就是定位和膨胀模板,并设置DataContext;然后尝试尽可能地“消失”(尽管您仍然可以在膨胀的模板中绑定到环境属性,如TextElement属性,然后来自ContentPresenter)。您不需要担心其他事情,它只是以一种相对苗条的方式膨胀模板。(我正在寻找最瘦的!)这是否意味着,一般来说,我应该在我的数据模板中使用ContentPresenter,因为它更轻(但在这样的数据模板中使用时,功能相当)?如果我正在编写一个新控件,那么就使用ContentControl作为基类吧?我已经编辑了答案,并提供了更多详细信息,说明何时使用ContentPresenter,何时使用ContentControlOk,我知道ContentPresenter应该在模板中使用,而不是ContentControl,但为什么?@sll-Con