Поделиться через


Создание элементов управления XAML с использованием C#

В этой статье описывается, как создать шаблонный элемент управления XAML для WinUI 3 с помощью C#. Шаблонные элементы управления наследуют свойства от Microsoft.UI.Xaml.Controls.Control и имеют визуальную структуру и поведение, которые можно настроить с помощью шаблонов элементов управления XAML.

Чтобы создать автономные компоненты WinUI 3 на C# для использования из приложений C# и C++/WinRT, см. статью Пошаговое руководство. Создание компонента C# с элементами управления WinUI 3 и его использование из приложения C++ пакета SDK для приложений для Windows.

Необходимые компоненты

  1. Настройте среду разработки по инструкциям из статьи Установка инструментов для Windows App SDK.
  2. Следуйте инструкциям по созданию простого проекта WinUI 3.

Создайте пустое приложение (BgLabelControlApp)

Начните с создания проекта в Microsoft Visual Studio. В диалоговом окне Создание нового проекта выберите шаблон проекта Blank App, Пустое, упакованное приложение (WinUI 3 в классических приложениях) и убедитесь, что выбрана версия языка C#. Задайте для проекта имя BgLabelControlApp, чтобы имена файлов соответствовали коду в приведенных ниже примерах.

Шаблон проекта пустого приложения

Добавление шаблонного элемента управления в приложение

Чтобы добавить шаблонный элемент управления, откройте меню Проект на панели инструментов или щелкните правой кнопкой мыши по проекту в обозревателе решений и выберите Добавить новый элемент. В разделе Visual C#->WinUI выберите шаблон Пользовательский элемент управления (WinUI 3). Присвойте этому элементу управления имя BgLabelControl и щелкните Добавить.

Обновление файла C# пользовательского элемента управления

В файле C# BgLabelControl.cs вы увидите, что конструктор определяет свойство DefaultStyleKey для нашего элемента управления. Этот ключ определяет шаблон по умолчанию, который будет использоваться, если потребитель элемента управления не укажет шаблон явным образом. Значение ключа определяет тип элемента управления. Мы встретим этот ключ позже при реализации файла универсального шаблона.

public BgLabelControl()
{
    this.DefaultStyleKey = typeof(BgLabelControl);
}

Шаблонный элемент управления будет иметь текстовую метку, которую можно задать программным способом в коде, в XAML или с помощью привязки данных. Чтобы система поддерживала актуальность метки для элемента управления, ее необходимо реализовать как DependencyPropety (зависимое свойство). Для этого сначала объявите строковое свойство с именем Label (Метка). Мы не используем резервную переменную, а будем сохранять и получать значение зависимого свойства вызовом методов GetValue и SetValue. Эти методы определены в объекте DependencyObject, от которого наследует Microsoft.UI.Xaml.Controls.Control.

public string Label
{
    get => (string)GetValue(LabelProperty);
    set => SetValue(LabelProperty, value);
}

Теперь объявите зависимое свойство и зарегистрируйте его в системе, вызвав DependencyProperty.Register. Этот метод определяет имя и тип для свойства Label, тип владельца свойства, класс BgLabelControl и значение по умолчанию для этого свойства.

DependencyProperty LabelProperty = DependencyProperty.Register(
    nameof(Label), 
    typeof(string),
    typeof(BgLabelControl), 
    new PropertyMetadata(default(string), new PropertyChangedCallback(OnLabelChanged)));

Этих двух шагов достаточно для реализации зависимого свойства, но для нашего примера потребуется еще и обработчик события OnLabelChanged, который не является обязательным. Это событие вызывается системой при каждом обновлении значения свойства. В нашем примере мы проверяем в нем, является ли текст метки пустой строкой, и если нет — обновляем переменную класса.

public bool HasLabelValue { get; set; }

private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    BgLabelControl labelControl = d as BgLabelControl; //null checks omitted
    String s = e.NewValue as String; //null checks omitted
    if (s == String.Empty)
    {
        labelControl.HasLabelValue = false;
    }
    else
    {
        labelControl.HasLabelValue = true;
    }
}

Дополнительные сведения о работе свойств зависимостей см. в статье Общие сведения о свойствах зависимостей.

Определение стиля по умолчанию для BgLabelControl

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

Файл универсального шаблона создается при добавлении пользовательского элемента управления (WinUI) в приложение. Этот файл называется Generic.xaml и создается в папке Themes в обозревателе решений. Имена папки и файла должны быть именно такими, чтобы платформа XAML могла найти стиль по умолчанию для шаблонного элемента управления. Удалите содержимое по умолчанию файла Generic.xaml и вставьте приведенную ниже разметку.

<!-- \Themes\Generic.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BgLabelControlApp">

    <Style TargetType="local:BgLabelControl" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:BgLabelControl">
                    <Grid Width="100" Height="100" Background="{TemplateBinding Background}">
                        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Label}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

В этом примере атрибуту TargetType элемента Style присвоено значение типа BgLabelControl в пространстве имен BgLabelControlApp. Именно этот тип мы указали выше в качестве значения для свойства DefaultStyleKey в конструкторе элемента управления, поэтому он является стилем по умолчанию для нашего элемента управления.

Свойство Text элемента TextBlock в шаблоне элемента управления привязано к зависимому свойству Label нашего элемента управления. Для привязки этого свойства используется расширение разметки TemplateBinding. Также в этом примере привязан фон Grid к зависимому свойству Background, которое унаследовано от класса Control.

Добавление экземпляра BgLabelControl на главную страницу пользовательского интерфейса

Откройте файл MainWindow.xaml, который содержит разметку XAML для главной страницы пользовательского интерфейса. Сразу после элемента Кнопка (внутри StackPanel), добавьте следующую разметку.

<local:BgLabelControl Background="Red" Label="Hello, World!"/>

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

Результат запуска шаблонного элемента управления

См. также