Condividi tramite


Creare controlli XAML con C#

Questo articolo illustra la creazione di un controllo XAML basato su modelli per WinUI 3 con C#. I controlli basati su modelli ereditano da Microsoft.UI.Xaml.Controls.Control e hanno una struttura visiva e un comportamento visivo che possono essere personalizzati tramite i modelli di controllo XAML.

Per creare componenti WinUI 3 autonomi in C# da usare in app C# e C++/WinRT, vedere l'articolo Procedura dettagliata: creare un componente C# con controlli WinUI 3 e utilizzarlo da un'app Windows App SDK in C++..

Prerequisiti

  1. Per configurare il computer di sviluppo, vedere Installare gli strumenti per Windows App SDK.
  2. Seguire le istruzioni su come Creare il primo progetto WinUI 3.

Creare un'app vuota (BgLabelControlApp)

Per iniziare, crea un nuovo progetto in Microsoft Visual Studio. Nella finestra di dialogo Crea un nuovo progetto selezionare il modello di progetto App vuota, Packaged (WinUI 3 in Desktop), assicurandosi di selezionare la versione del linguaggio C#. Impostare il nome del progetto su "BgLabelControlApp" in modo che i nomi di file siano allineati al codice riportato negli esempi seguenti.

Modello di progetto di app vuota

Aggiungere all'app un controllo basato su modelli

Per aggiungere un controllo basato su modelli, fare clic sul menu Progetto nella barra degli strumenti oppure fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Aggiungi nuovo elemento. In Visual C#->WinUI selezionare il modello Controllo personalizzato (WinUI 3). Assegnare al nuovo controllo il nome "BgLabelControl" e fare clic su Aggiungi.

Aggiornare il controllo personalizzato per il file C#

Nel file C#, BgLabelControl.cs, si noti che il costruttore definisce la proprietà DefaultStyleKey per il controllo. Questa chiave identifica il modello predefinito che verrà usato se il consumer del controllo non specifica in modo esplicito un modello. Il valore della chiave è il tipo del controllo. Questa chiave verrà usata più avanti quando si implementa il file di modello generico.

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

Il controllo basato su modelli avrà un'etichetta di testo che può essere impostata a livello di programmazione nel codice, in XAML o tramite data binding. Per consentire al sistema di mantenere aggiornato il testo dell'etichetta del controllo, è necessario implementarlo come DependencyPropety. A tale scopo, è necessario prima dichiarare una proprietà di stringa e chiamarla Label. Anziché usare una variabile sottostante, il valore della proprietà di dipendenza viene impostato e ottenuto chiamando GetValue e SetValue. Questi metodi vengono forniti da DependencyObject, ereditato da Microsoft.UI.Xaml.Controls.Control.

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

Dichiarare quindi la proprietà di dipendenza e registrarla nel sistema chiamando DependencyProperty.Register. Questo metodo specifica il nome e il tipo della proprietà Label, il tipo di proprietario della proprietà, la classe BgLabelControl, e il valore predefinito della proprietà.

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

Questi due passaggi sono sufficienti a implementare una proprietà di dipendenza. In questo esempio, tuttavia, si aggiungerà un gestore facoltativo per l'evento OnLabelChanged. Questo evento viene generato dal sistema ogni volta che viene aggiornato il valore della proprietà. In questo caso si verifica se il nuovo testo dell'etichetta è una stringa vuota o meno e si aggiorna di conseguenza una variabile di classe.

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;
    }
}

Per altre informazioni sul funzionamento delle proprietà di dipendenza, vedere Panoramica delle proprietà di dipendenza.

Definire lo stile predefinito per BgLabelControl

Un controllo basato su modelli deve fornire un modello di stile predefinito che viene usato se l'utente del controllo non imposta in modo esplicito uno stile. In questo passaggio verrà modificato il file modello generico per il controllo.

Il file di modello generico viene generato quando si aggiunge il Controllo personalizzato (WinUI) all’app. Il file è denominato "Generic.xaml" e viene generato nella cartella Temi in Esplora soluzioni. I nomi di file e cartelle sono necessari affinché il framework XAML trovi lo stile predefinito per un controllo basato su modelli. Eliminare il contenuto predefinito di Generic.xaml e incollare il markup riportato di seguito.

<!-- \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>

In questo esempio è possibile osservare che l'attributo TargetType dell'elemento Style è impostato sul tipo BgLabelControl nello spazio dei nomi BgLabelControlApp. Questo tipo corrisponde al valore specificato in precedenza per la proprietà DefaultStyleKey nel costruttore del controllo che lo identifica come lo stile predefinito per il controllo.

La proprietà Text di TextBlock nel modello di controllo è associata alla proprietà di dipendenza Label del controllo. La proprietà viene associata usando l'estensione di markup TemplateBinding. In questo esempio viene anche associato lo sfondo Grid alla proprietà di dipendenza Background ereditata dalla classe Control.

Aggiungere un'istanza di BgLabelControl alla pagina dell'interfaccia utente principale

Apri MainWindow.xaml, che contiene il markup XAML per la nostra pagina dell'interfaccia utente principale. Immediatamente dopo l'elemento Button, all'interno di StackPanel, aggiungi il markup seguente.

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

Compilare ed eseguire l'app. Verrà visualizzato il controllo basato su modelli, con l'etichetta e il colore di sfondo specificati.

Risultato del controllo basato su modelli

Vedi anche