21

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

那么UserControlover 有什么意义ContentControl呢?

更新:

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

注意:您可以从代码隐藏中删除基类,因为它实际上是一个分部类,该类的另一“部分”是由 XAML 设计器通过代码生成创建的。因此,基类将始终定义为 XAML 文件的根元素,因此您可以在代码隐藏中简单地省略它,因为它是多余的。

这是更新的 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();
    }
}
4

6 回答 6

37

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

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

ContentControl 的 ControlTemplate

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

UserControl 的 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>
于 2017-01-18T14:41:47.650 回答
9

基本上,UserControl上课是为了方便。它使我们能够从已经存在的控件构建 UI 的一小部分,而ContentControls 实际上是用于创建新控件,通常具有单一目的和/或功能。

我读了一本书,对此有很好的解释,幸运的是,有人“将其副本放在网上”。从链接的书中:

UserControl 类是一个容器类,它充当相关控件集合的“黑盒”容器。如果您需要一组三个控件始终一起出现并允许轻松地相互交谈,那么实现这一目标的一个可能的候选者是 UserControl 类。

然后关于是否创建一个CustomControl

以下是决策过程的摘要:

尽可能使用框架。WPF 提供了多种可扩展控件,因此请确保 WPF 控件中不存在所需的功能。

在许多情况下,您正在使用的数据结构需要不同的视觉表示。使用 ControlTemplates 和 DataTemplates 通常可以获得所需的功能。

查看 ValueConverters 以了解它们是否可以帮助弥合库存功能与您需要的功能之间的差距。

最后,看看您是否不能使用附加属性扩展现有行为。

看看你的问题的深入答案:

释放 WPF 控件开发

更新>>>

@MarqueIV,更直接地回答您的问题:UserControl为方便起见,我们提供了该课程。而已。如果将 WPF 添加CustomControl到项目中,您将看到它没有 XAML 文件。这意味着您必须在文件夹中调用Generic.xaml的文件中设计您控制标记Themes。该类UserControl为我们提供了一个 XAML 文件,以便更轻松地创建它们......所以更方便......就是这样。这就是原因。

于 2013-09-13T08:39:49.757 回答
3

与此不同的一件事是ContentControl覆盖UserControlOnCreateAutomationPeer方法,您可能会寻找它。也许它有一些不同于ContentControl.

此方法创建一个UserControlAutomationPeer-instance

于 2013-09-13T09:05:54.640 回答
1

ContentControl
ContentControl 直接派生自 Control 类。
它承载单个元素,该元素可以是一个容器(例如,Grid、Stackpanel,...),它本身承载多个元素(例如,带有 TextBlock 和 Image 子项的 StackPanel)。
它的外观可以通过 DataTemplate 进行修改。
请参阅MSDN 备注部分

UserControl
UserControl 派生自 ContentControl。
它不支持模板,因此没有自定义。
它不会像 Window 那样自动捕捉焦点。
仍然在MSDN 备注部分

于 2016-11-04T16:28:29.897 回答
0

UserControl 和 ContentControl 可能实现相同,但用例不同。

我们需要回答两个问题,什么时候使用 UserControl 或 CustomControl? 以及何时使用 ContentControl?.

那么何时使用 UserControl 或 CustomControl?

每当我想要一个可重用的 UI
时,例如,如果我想要一个 FileDialogBrowser,意思是一个按钮旁边有一个 TextBlock,所以每当我按下按钮并且用户选择一个文件时,我都会在 TextBlock 中显示所选文件。

相同但不完全适用于 customControl 但是在这里我们想做一些更复杂的事情,无论如何这不是问题。

那么什么时候使用ContentControl呢?

说起来有点棘手,但是假设我们想要一个带有消息的进度条,这样我们就可以从 BusyIndi​​cator 或 Border 继承,但是如果我们使用 ContentControl,我们就可以控制它里面的内容。我们可以让它包裹其他 xaml 元素。

希望这可以帮助

于 2014-06-10T20:00:20.350 回答
0

UserControl 是一个复合控件。它与 ASP.NET Webforms 中的 UserControl 具有类似的概念。这意味着它是一个由许多控件组成的控件。在 WPF 中,创建用户控件支持 Visual Studio 2008 及更高版本的设计器。ContentControl 是一个旨在将单个控件作为其内容的控件。

有关详细信息:http: //msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.aspx

于 2013-09-13T08:44:25.310 回答