Какая разница между UserControl и ContentControl?

Обновление

Как показано в помеченном ответе, Reflector подтверждает, что UserControl переопределяет несколько методов, поэтому, хотя интерфейс полностью идентичен между этими двумя, и вы можете использовать любой из них с конструктором VS, есть небольшие различия в поведении. Я оставлю это на усмотрение читателя, чтобы изучить эти различия больше, но здесь код подкласса...

public class UserControl : ContentControl
{
    // Fields
    private static DependencyObjectType _dType;

    // Methods
    static UserControl()
    {
        FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(
            typeof(UserControl),
            new FrameworkPropertyMetadata(typeof(UserControl)));

        _dType = DependencyObjectType.FromSystemTypeInternal(
            typeof(UserControl));

        UIElement.FocusableProperty.OverrideMetadata(
            typeof(UserControl),
            new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));

        KeyboardNavigation.IsTabStopProperty.OverrideMetadata(
            typeof(UserControl),
            new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));

        Control.HorizontalContentAlignmentProperty.OverrideMetadata(
            typeof(UserControl),
            new FrameworkPropertyMetadata(HorizontalAlignment.Stretch));

        Control.VerticalContentAlignmentProperty.OverrideMetadata(
            typeof(UserControl),
            new FrameworkPropertyMetadata(VerticalAlignment.Stretch));
    }

    internal override void AdjustBranchSource(RoutedEventArgs e)
    {
        e.Source = this;
    }

    protected override AutomationPeer OnCreateAutomationPeer()
    {
        return new UserControlAutomationPeer(this);
    }

    // Properties
    internal override DependencyObjectType DTypeThemeStyleKey
    {
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        get
        {
            return _dType;
        }
    }

    internal override FrameworkElement StateGroupsRoot
    {
        get
        {
            return (base.Content as FrameworkElement);
        }
    }
}

Оригинальный вопрос:

Согласно всей документации, когда вы создаете элемент управления без внешнего вида, вы должны создавать подкласс UserControl. Тем не менее, UserControl является простым подклассом ContentControl, но он, похоже, ничего не добавляет к нему с точки зрения интерфейса. Таким образом, вы можете взять этот сгенерированный дизайнером код и изменить базовый класс на ContentControl, и он, похоже, будет работать точно так же.

Так какой смысл UserControl над ContentControl?

Обновление: для тех, кто продолжает отвечать на вопросы VS, я считаю, что это не так. Попробуй. Создайте новый UserControl в Visual Studio. Затем в полученном XAML файле измените корневой тег на ContentControl. Затем в связанном файле класса измените базовый класс на ContentControl. Похоже, что он работает точно так же, включая полную поддержку дизайнера WYSIWYG.

Здесь обновленный 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>

... и связанный файл класса...

using System.Windows.Controls;

namespace Playground.ComboTest
{
    public partial class InlineTextEditor : ContentControl
    {
        public InlineTextEditor()
        {
            InitializeComponent();
        }
    }
}

Ответ 1

UserControls хорошо подходят для объединения существующих элементов управления, когда вам не нужно предоставлять потребителю ControlTemplate. Это означает, что UserControls не являются безразличными. Почему бы просто не использовать ContentControl, поскольку он может связать XAML как UserControl, и реализация похожа на UserControl? Ну, есть несколько важных технических различий, которые вы должны знать:

  • UserControls устанавливают себя как источник для RoutedEvents, созданный элементами внутри них. Это означает, что, когда элемент вне UserControl получает событие с барботированием, Source является UserControl, а не тем, с которым вы взаимодействовали в UserControl. В философском понимании того, что вы часто слышите о UserControls, "Это для агрегации существующих элементов управления", это имеет смысл, поскольку вы хотите, чтобы родительский элемент контейнера думал о вашем UserControl как о едином модуле. Например, ваш UserControl содержит кнопку, которую пользователь нажимает, а сетка, содержащая экземпляр UserControl, получает событие MouseLeftButtonUp, но кнопка не является источником события, ваш UserControl.
  • UserControl устанавливает Focusable и IsTabStop в false. Вы можете увидеть философию, демонстрирующую себя здесь снова, так как мы не хотим, чтобы группировка существующих элементов управления была Focusable.
  • UserControl устанавливает HorizontalAlignment и VerticalAlignment для растягивания. A ContentControl автоматически будет установлен на Left и Top.
  • UserControl собственный Реализация AutomationPeer позволяет вам изменять VisualStates с помощью VisualStateManager.GoToState(). ContentControl требует, чтобы VisualStateGroups находились на верхнем уровне, и вы должны называть их VisualStateManager.GoToElementState().
  • UserControl собственный элемент управления ControlTemplate обертывает ваш контент на границе. Это снова имеет смысл, когда вы думаете о философском случае использования для UserControl.
  • UserControl собственный ControlTemplate предоставляет больше TemplateBindings, чем ContentControl. Это своего рода повторение некоторых из вышеперечисленных пунктов, но объясняет, как они возможны. Напомним, что UserControl обеспечивает границу, поэтому это относится к некоторым из этих бесплатных шаблонов, которые вы видите ниже. Это позволяет уважать свойства BorderBrush, BorderThickness, Background и Padding вашего элемента управления, которые иначе не работали бы только с ContentControl. Например, если вы просто получаете свой контроль из ContentControl и устанавливаете свойство Background в корневом элементе ContentControl, это не сработает, потому что ControlTemplate ContentControl не имеет шаблона для фона. Конечно, вы можете установить свойство 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>

Ответ 2

По сути, класс UserControl существует для удобства. Это позволяет нам создавать небольшие части пользовательского интерфейса из уже существующих элементов управления, тогда как ContentControl действительно предназначен для создания новых элементов управления, как правило, с одной целью и/или функциональностью.

Я прочитал книгу, в которой было хорошее объяснение этого, и, к счастью, кто-то "разместил ее в Интернете". Из связанной книги:

Класс UserControl является классом контейнера, который действует как контейнер "черного ящика" для коллекции связанных элементов управления. Если вам нужен набор из трех элементов управления, чтобы всегда появляться вместе и можно легко поговорить друг с другом, то вероятным кандидатом на то, чтобы это произошло, является класс UserControl.

Затем относительно того, создавать ли CustomControl:

Ниже приводится краткое изложение процесса принятия решения:

Используйте рамки как можно больше. WPF предоставляет множество расширяемых элементы управления, поэтому убедитесь, что требуемая функциональность уже не существует в WPF control.

Во многих случаях структура данных, с которой вы работаете, требует другого визуального представления. Использование ControlTemplates и DataTemplates часто может дать вам функциональность тебе нужно.

Посмотрите на ValueConverters, чтобы увидеть, могут ли они помочь преодолеть разрыв между стоковая функциональность и что вам нужно.

Наконец, посмотрите, не можете ли вы расширить существующее поведение с помощью прикрепленных свойств.

Посмотрите подробный ответ на ваш вопрос:

Разработка управления WPF запущена

ОБНОВЛЕНИЕ >>>

@MarqueIV, чтобы ответить на ваш вопрос более прямо: класс UserControl предоставлен нам для удобства. Это. Если вы добавите WPF CustomControl в свой проект, вы увидите, что у него нет файла XAML. Это означает, что вы должны создать свою разметку управления в файле с именем Generic.xaml в папке Themes. Класс UserControl дает нам XAML файл, чтобы их было проще создавать... так что удобнее... это так. Это причина.

Ответ 3

Одна вещь, отличная от ContentControl, заключается в том, что UserControl переопределяет метод OnCreateAutomationPeer, вы можете это искать. Возможно, он имеет несколько разных пользовательских интерфейсов, чем ContentControl.

Этот метод создает UserControlAutomationPeer -nstance.

Ответ 4

ContentControl
ContentControl напрямую вытекает из класса Control.
В нем размещается один элемент, который может быть контейнером (например, Grid, Stackpanel,...), на котором размещается несколько элементов (например, StackPanel с TextBlock и изображениями).
Его внешний вид может быть изменен с помощью DataTemplate.
См. Раздел примечаний MSDN.

UserControl
Пользователь UserControl происходит из ContentControl.
Он НЕ поддерживает шаблоны, поэтому нет настройки.
Он не фокусируется автоматически, как на Окне.
Еще в разделе

Ответ 5

UserControl - это составной элемент управления. Он имеет аналогичную концепцию с UserControl в ASP.NET Webforms. Это означает, что это элемент управления, состоящий из многих элементов управления. В WPF создание пользовательского элемента управления поддерживает дизайнеров в Visual Studio 2008 и выше. ContentControl - это элемент управления, который должен иметь единый элемент управления в качестве своего содержимого.

Для получения дополнительной информации: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.aspx

Ответ 6

UserControl и ContentControl могут быть одной и той же реализацией, но вариант использования не является тем же.

нам нужно ответить на два вопроса , когда использовать UserControl или CustomControl? и , когда использовать ContentControl?.

поэтому, когда использовать UserControl или CustomControl?

Всякий раз, когда я хочу иметь повторно используемую часть пользовательского интерфейса
например, если я хочу иметь FileDialogBrowser, имея в виду кнопку с TextBlock рядом с ней, поэтому всякий раз, когда я нажимаю кнопку, и пользователь выбирает файл, я покажу выбранный файл в TextBlock.

то же самое, но не совсем подходит для customControl, но здесь мы хотим сделать что-то более сложное, в любом случае это не проблема.

поэтому, когда использовать ContentControl?

Это немного сложно сказать, но позвольте сказать, что мы хотим иметь progressBar с сообщением поэтому мы можем наследовать от BusyIndicator или Border, однако, если мы используем ContentControl, у нас есть контроль, который может контролировать содержимое внутри него. мы можем обернуть его вокруг других элементов xaml.

надеюсь, что это поможет