wpf - UserControl 和 ContentControl 有什么区别?

标签 wpf user-controls subclass

根据所有文档,当您创建非无外观控件时,您应该继承 UserControl .但是,UserControlContentControl 的简单子(monad)类但它似乎没有向它添加任何东西,界面方面。因此,您可以使用该设计器生成的代码并将基类更改为 ContentControl它似乎仍然工作完全一样。

那么 UserControl 的意义何在?超过 ContentControl ?

更新:

对于那些不断回答的人,Visual Studio 对待他们的方式不同,我认为情况并非如此。尝试一下!新建UserControl在 Visual Studio 中,然后在生成的 XAML 文件中,将根标记更改为 ContentControl .然后在关联的类文件中,将基类更改为ContentControl或者像我在这里所做的那样简单地删除它(请参阅注释),您会看到它的工作方式完全相同,包括完整的所见即所得设计器支持。

Note: You can delete the base class from the code-behind because it's actually a partial class with the other 'part' of the class being created by the XAML designer via code-generation. As such, the base class will always be defined as the root element of the XAML file, so you can simply omit it in the code-behind as it's redundant.



这是更新的 XAML ......
<ContentControl x:Class="Playground.ComboTest.InlineTextEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <TextBlock Text="Success" />

</ContentControl>

...以及相关的类文件...
namespace Playground.ComboTest {

    public partial class InlineTextEditor {

        public InlineTextEditor()
            => InitializeComponent();
    }
}

最佳答案

当您不需要为使用者提供 ControlTemplate 时,UserControls 非常适合聚合现有控件。这意味着 UserControls 不是没有看头的 .为什么不直接使用 ContentControl,因为它可以像 UserControl 一样耦合 XAML,并且实现看起来类似于 UserControl?好吧,您必须知道几个重要的技术差异:

  • UserControls 将自己设置为 RoutedEvents 的源由其中的元素引发。这意味着当 UserControl 之外的元素收到冒泡事件时,Source 是 UserControl,而不是您在 UserControl 中交互的东西。从您经常听到的有关 UserControls 的哲学意义上说,“它用于聚合现有控件”,这是有道理的,因为您希望父容器元素将您的 UserControl 视为一个单元。例如,您的 UserControl 包含用户单击的按钮,并且包含您的 UserControl 实例的 Grid 接收 MouseLeftButtonUp 事件,但 Button 不是事件的源,您的 UserControl 是。
  • UserControl 将 Focusable 和 IsTabStop 设置为 false .您可以在这里再次看到这一理念,因为我们不希望现有控件的分组成为可聚焦的。
  • UserControl 将 Horizo​​ntalAlignment 和 VerticalAlignment 设置为 Stretch . ContentControl 将自动设置为 Left 和 Top。
  • UserControl 自己的 AutomationPeer implementation允许您通过 更改 VisualStates VisualStateManager.GoToState() . ContentControl 要求 VisualStateGroups 位于顶层,您必须使用 VisualStateManager.GoToElementState() 调用它们.
  • UserControl 自己的 ControlTemplate 将您的内容包装在边框中 .在考虑 UserControl 的哲学用例时,这又是有意义的。
  • UserControl自带的ControlTemplate提供了更多的TemplateBindings 比内容控制。这是对上述一些项目的概括,但解释了它们是如何可能的。回想一下,UserControl 提供了一个 Border,以便与您在下面看到的一些免费 TemplateBindings 相关。这样可以尊重控件上的 BorderBrush、BorderThickness、Background 和 Padding 属性,否则这些属性仅适用于 ContentControl。例如,如果您只是从 ContentControl 派生控件并在根 ContentControl 元素上设置 Background 属性,它将不起作用,因为 ContentControl 的 ControlTemplate 没有用于背景的 TemplateBinding。当然,您可以在包含所需元素的子内容元素上设置 Background 属性,例如 Grid,但这不是理想的 IMO。

  • ContentControl's ControlTemplate


    <ControlTemplate TargetType="ContentControl">
      <ContentPresenter
       Content="{TemplateBinding ContentControl.Content}"
       ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
       ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" />
    </ControlTemplate>
    

    UserControl's ControlTemplate


    <ControlTemplate TargetType="UserControl">
      <Border BorderBrush="{TemplateBinding Border.BorderBrush}"
       BorderThickness="{TemplateBinding Border.BorderThickness}"
       Background="{TemplateBinding Panel.Background}"
       Padding="{TemplateBinding Control.Padding}"
       SnapToDevicePixels="True">
        <ContentPresenter
         HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
         VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
         SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
         ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
         ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
         Content="{TemplateBinding ContentControl.Content}" />
      </Border>
    </ControlTemplate>
    

    关于wpf - UserControl 和 ContentControl 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18781679/

    相关文章:

    wpf - 将多个参数传递给 Prism 的 EventAggregator

    WPF 数据绑定(bind)到链表

    asp.net - 如何查找用户控件的父页面的url

    java - 将子类对象添加到 ArrayList

    c# - 应用程序加载时出现无法追踪的异常

    c# - 我如何知道 TextRange 是否是或包含超链接?

    wpf - Loaded 之后和显示用户控件之前是否有任何事件?

    c# - 如何在 WPF 的 tabItem 中控制焦点

    hibernate - 子类中的 Nhibernate/hibernate 鉴别器

    c++ - 返回模板子类