Freigeben über


Exemplarische Vorgehensweise: Hosten eines zusammengesetzten WPF-Steuerelements in Windows Forms

Windows Presentation Foundation (WPF) bietet eine umfangreiche Umgebung zum Erstellen von Anwendungen. Wenn Sie jedoch eine erhebliche Investition in Den Windows Forms-Code haben, kann es effektiver sein, Ihre vorhandene Windows Forms-Anwendung mit WPF zu erweitern, anstatt sie von Grund auf neu zu schreiben. Ein gängiges Szenario ist, wenn Sie ein oder mehrere Steuerelemente einbetten möchten, die mit WPF in Ihrer Windows Forms-Anwendung implementiert sind. Weitere Informationen zum Anpassen von WPF-Steuerelementen finden Sie unter Steuerelementanpassungen.

In dieser Anleitung werden Sie durch eine Anwendung geführt, die ein zusammengesetztes WPF-Steuerelement hostet, um Dateneingaben in einer Windows Forms-Anwendung vorzunehmen. Das zusammengesetzte Steuerelement ist in eine DLL verpackt. Dieses allgemeine Verfahren kann auf komplexere Anwendungen und Steuerelemente erweitert werden. Diese exemplarische Vorgehensweise wurde so gestaltet, dass sie in Darstellung und Funktionalität nahezu identisch mit Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in WPF ist. Der Hauptunterschied besteht darin, dass das Hostingszenario umgekehrt wird.

Diese exemplarische Vorgehensweise ist in zwei Abschnitte unterteilt. Im ersten Abschnitt wird die Implementierung des zusammengesetzten WPF-Steuerelements kurz beschrieben. Im zweiten Abschnitt wird ausführlich beschrieben, wie das zusammengesetzte Steuerelement in einer Windows Forms-Anwendung gehostet wird, wie Ereignisse vom Steuerelement empfangen werden und wie auf einige Eigenschaften des Steuerelements zugegriffen wird.

In dieser exemplarischen Vorgehensweise werden u. a. folgende Aufgaben veranschaulicht:

  • Implementieren des zusammengesetzten WPF-Steuerelements

  • Implementieren der Windows Forms-Hostanwendung.

Eine vollständige Codeauflistung der Aufgaben in dieser exemplarischen Vorgehensweise finden Sie unter Beispiel zum Hosten eines zusammengesetzten WPF-Steuerelements in Windows Forms.

Voraussetzungen

Sie benötigen Visual Studio, um diese Anleitung abzuschließen.

Implementieren des zusammengesetzten WPF-Steuerelements

Das in diesem Beispiel verwendete zusammengesetzte WPF-Steuerelement ist ein einfaches Dateneingabeformular, das den Namen und die Adresse des Benutzers verwendet. Wenn der Benutzer auf eine von zwei Schaltflächen klickt, um anzugeben, dass die Aufgabe abgeschlossen ist, löst das Steuerelement ein benutzerdefiniertes Ereignis aus, um diese Informationen an den Host zurückzugeben. Die folgende Abbildung zeigt das gerenderte Steuerelement.

Die folgende Abbildung zeigt ein zusammengesetztes WPF-Steuerelement:

Screenshot: Einfaches WPF-Steuerelement

Projekt erstellen

So starten Sie das Projekt:

  1. Starten Sie Visual Studio, und öffnen Sie das Dialogfeld Neues Projekt.

  2. Wählen Sie in Visual C# in der Kategorie „Windows” die Vorlage WPF-Benutzersteuerelementbibliothek aus.

  3. Benennen Sie das neue Projekt MyControls.

  4. Geben Sie für den Speicherort einen bequem benannten Ordner auf oberster Ebene an, z. B. WindowsFormsHostingWpfControl. Später platzieren Sie die Hostanwendung in diesem Ordner.

  5. Klicken Sie auf OK, um das Projekt zu erstellen. Das Standardprojekt enthält ein einzelnes Steuerelement mit dem Namen UserControl1.

  6. Benennen Sie im Projektmappen-Explorer UserControl1 in MyControl1 um.

Ihr Projekt sollte Verweise auf die folgenden System-DLLs haben. Wenn eine dieser DLLs standardmäßig nicht enthalten ist, fügen Sie sie ihrem Projekt hinzu.

  • PresentationCore

  • PresentationFramework

  • System

  • WindowsBase

Erstellen der Benutzeroberfläche

Die Benutzeroberfläche für das zusammengesetzte Steuerelement wird mit XAML (Extensible Application Markup Language) implementiert. Die Benutzeroberfläche des zusammengesetzten Steuerelements besteht aus fünf TextBox-Elementen. Jedes TextBox-Element weist ein zugeordnetes TextBlock Element auf, das als Beschriftung dient. Unten gibt es zwei Button-Elemente, OK und Abbrechen. Wenn der Benutzer auf eine der Schaltflächen klickt, löst das Steuerelement ein benutzerdefiniertes Ereignis aus, um die Informationen an den Host zurückzugeben.

Grundlegendes Layout

Die verschiedenen Benutzerschnittstellen-Elemente sind in einem Grid-Element enthalten. Sie können Grid verwenden, um den Inhalt des zusammengesetzten Steuerelements auf die gleiche Weise wie ein Table-Element in HTML anzuordnen. WPF verfügt auch über ein Table-Element, aber Grid ist einfacher und besser für einfache Layoutaufgaben geeignet.

Der folgende XAML-Code zeigt das grundlegende Layout. Dieser XAML-Code definiert die gesamtstruktur des Steuerelements, indem die Anzahl der Spalten und Zeilen im Grid-Element angegeben wird.

Ersetzen Sie in „MyControl1.xaml“ den vorhandenen XAML-Code durch den folgenden.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.MyControl1"
      Background="#DCDCDC"
      Width="375"
      Height="250"
      Name="rootElement"
      Loaded="Init">

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
</Grid>

Hinzufügen von TextBlock- und TextBox-Elementen zum Raster

Sie platzieren ein UI-Element im Raster, indem Sie die RowProperty und ColumnProperty Attribute des Elements auf die entsprechende Zeilen- und Spaltennummer festlegen. Denken Sie daran, dass Zeilen- und Spaltennummerierung nullbasiert sind. Sie können ein Element über mehrere Spalten erstrecken, indem Sie das Attribut ColumnSpanProperty setzen. Weitere Informationen zu Grid Elementen finden Sie unter Erstellen eines Grid-Elements.

Der folgende XAML-Code zeigt die TextBox- und TextBlock-Elemente des zusammengesetzten Steuerelements mit deren Attributen RowProperty und ColumnProperty, die so festgelegt sind, dass die Elemente im Raster richtig platziert werden.

Fügen Sie in „MyControl1.xaml“ im Grid-Element den folgenden XAML-Code hinzu.

  <TextBlock Grid.Column="0"
        Grid.Row="0" 
        Grid.ColumnSpan="4"
        Margin="10,5,10,0"
        HorizontalAlignment="Center"
        Style="{StaticResource titleText}">Simple WPF Control</TextBlock>

  <TextBlock Grid.Column="0"
        Grid.Row="1"
        Style="{StaticResource inlineText}"
        Name="nameLabel">Name</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="1"
        Grid.ColumnSpan="3"
        Name="txtName"/>

  <TextBlock Grid.Column="0"
        Grid.Row="2"
        Style="{StaticResource inlineText}"
        Name="addressLabel">Street Address</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="2"
        Grid.ColumnSpan="3"
        Name="txtAddress"/>

  <TextBlock Grid.Column="0"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="cityLabel">City</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="3"
        Width="100"
        Name="txtCity"/>

  <TextBlock Grid.Column="2"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="stateLabel">State</TextBlock>
  <TextBox Grid.Column="3"
        Grid.Row="3"
        Width="50"
        Name="txtState"/>

  <TextBlock Grid.Column="0"
        Grid.Row="4"
        Style="{StaticResource inlineText}"
        Name="zipLabel">Zip</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="4"
        Width="100"
        Name="txtZip"/>

Stylen der UI-Elemente

Viele der Elemente im Dateneingabeformular haben ein ähnliches Erscheinungsbild, was bedeutet, dass sie identische Einstellungen für mehrere ihrer Eigenschaften haben. Anstatt die Attribute jedes Elements separat festzulegen, verwendet der vorherige XAML Style Elemente, um Standardeigenschafteneinstellungen für Klassen von Elementen zu definieren. Dieser Ansatz reduziert die Komplexität des Steuerelements und ermöglicht es Ihnen, das Erscheinungsbild mehrerer Elemente durch ein einzelnes Style-Attribut zu ändern.

Die Style-Elemente sind in der Grid-Eigenschaft des Resources-Elements enthalten, sodass sie von allen Elementen im Steuerelement verwendet werden können. Wenn ein Stil benannt ist, wenden Sie ihn auf ein Element an, indem Sie ein Style-Element hinzufügen, das als Wert den Stilnamen hat. Stile, die unbenannt sind, werden zum Standardstil für das Element. Weitere Informationen zu WPF-Stilen finden Sie unter Erstellen von Formatierungen und Vorlagen.

Der folgende XAML-Code zeigt die Style-Elemente für das zusammengesetzte Steuerelement. Um zu sehen, wie die Stile auf Elemente angewendet werden, siehe das vorherige XAML. Beispielsweise hat das letzte TextBlock-Element den Stil inlineText, und das letzte TextBox-Element verwendet den Standardstil.

Fügen Sie in „MyControl1.xaml“ den folgenden XAML-Code direkt nach dem Grid-Startelement hinzu.

<Grid.Resources>
  <Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="12"/>
  </Style>
  <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
  <Style TargetType="{x:Type Button}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="Width" Value="60"/>
  </Style>
  <Style TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
</Grid.Resources>

Hinzufügen der Schaltflächen "OK" und "Abbrechen"

Die letzten Elemente des zusammengesetzten Steuerelements sind die OK und AbbrechenButton-Elemente, die nur die ersten beiden Spalten der letzten Zeile von Grid belegen. Diese Elemente verwenden einen gemeinsamen Ereignishandler, ButtonClicked, und den Standardstil Button, der im vorherigen XAML definiert ist.

Fügen Sie in „MyControl1.xaml“ den folgenden XAML-Code nach dem letzten TextBox-Element hinzu. Der XAML-Teil des zusammengesetzten Steuerelements ist jetzt vollständig.

<Button Grid.Row="5"
        Grid.Column="0"
        Name="btnOK"
        Click="ButtonClicked">OK</Button>
<Button Grid.Row="5"
        Grid.Column="1"
        Name="btnCancel"
        Click="ButtonClicked">Cancel</Button>

Implementieren der CodeBehind-Datei

Die Code-Behind-Datei MyControl1.xaml.cs implementiert drei wesentliche Aufgaben:

  1. Behandelt das Ereignis, das auftritt, wenn der Benutzer auf eine der Schaltflächen klickt.

  2. Sie ruft die Daten aus den TextBox-Elementen ab und verpackt sie in einem benutzerdefinierten Ereignisargumentobjekt.

  3. Sie löst das benutzerdefinierte OnButtonClick-Ereignis aus, das den Host darüber benachrichtigt, dass die benutzende Person die Eingabe abgeschlossen hat, und übergibt die Daten zurück an den Host.

Das Steuerelement macht außerdem eine Reihe von Farb- und Schriftarteigenschaften verfügbar, mit denen Sie die Darstellung ändern können. Im Gegensatz zur WindowsFormsHost-Klasse, die ein Windows Forms-Steuerelement hostet, stellt die ElementHost-Klasse nur die Background-Eigenschaft des Steuerelements bereit. Um die Ähnlichkeit zwischen diesem Codebeispiel und dem Beispiel aus Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in WPF beizubehalten, macht das Steuerelement die verbleibenden Eigenschaften direkt verfügbar.

Die grundlegende Struktur der Code-Behind Datei

Die CodeBehind-Datei besteht aus einem einzigen Namespace, MyControls, der zwei Klassen, MyControl1 und MyControlEventArgs, enthält.

namespace MyControls
{
  public partial class MyControl1 : Grid
  {
    //...
  }
  public class MyControlEventArgs : EventArgs
  {
    //...
  }
}

Die erste Klasse, MyControl1, ist eine partielle Klasse, die den Code enthält, der die Funktionalität der in MyControl1.xaml definierten Benutzeroberfläche implementiert. Wenn MyControl1.xaml analysiert wird, wird der XAML-Code in dieselbe Teilklasse konvertiert, und die beiden partiellen Klassen werden zusammengeführt, um das kompilierte Steuerelement zu bilden. Aus diesem Grund muss der Klassenname in der CodeBehind-Datei mit dem übereinstimmen, der MyControl1.xaml zugewiesen wurde, und er muss vom Stammelement des Steuerelements erben. Die zweite Klasse, MyControlEventArgs, ist eine Klasse für Ereignisargumente, die zum Senden der Daten zurück an den Host verwendet wird.

Öffnen Sie MyControl1.xaml.cs. Ändern Sie die vorhandene Klassendeklaration so, dass sie den folgenden Namen hat und von Griderbt.

public partial class MyControl1 : Grid

Initialisieren des Steuerelements

Der folgende Code implementiert mehrere grundlegende Aufgaben:

  • Deklarieren eines privaten Ereignisses, OnButtonClick, und seines zugeordneten Delegats MyControlEventHandler.

  • Erstellt mehrere private globale Variablen, die die Daten des Benutzers speichern. Diese Daten werden durch entsprechende Eigenschaften verfügbar gemacht.

  • Implementieren eines Handlers, Init, für das Loaded-Ereignis des Steuerelements. Dieser Handler initialisiert die globalen Variablen, indem er ihnen die in MyControl1.xaml definierten Werte zuweist. Zu diesem Zweck wird Name verwendet, der einem typischen TextBlock-Element (nameLabel) zugewiesen wurde, um auf die Eigenschaftseinstellungen dieses Elements zuzugreifen.

Löschen Sie den vorhandenen Konstruktor, und fügen Sie Ihrer Klasse MyControl1 den folgenden Code hinzu.

public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;
private FontWeight _fontWeight;
private double _fontSize;
private FontFamily _fontFamily;
private FontStyle _fontStyle;
private SolidColorBrush _foreground;
private SolidColorBrush _background;

private void Init(object sender, EventArgs e)
{
    //They all have the same style, so use nameLabel to set initial values.
    _fontWeight = nameLabel.FontWeight;
    _fontSize = nameLabel.FontSize;
    _fontFamily = nameLabel.FontFamily;
    _fontStyle = nameLabel.FontStyle;
    _foreground = (SolidColorBrush)nameLabel.Foreground;
    _background = (SolidColorBrush)rootElement.Background;
}

Verarbeiten der Klickereignisse der Schaltflächen

Der Benutzer gibt an, dass die Dateneingabeaufgabe abgeschlossen ist, indem sie entweder auf die Schaltfläche OK oder auf die Schaltfläche Abbrechen klicken. Beide Schaltflächen verwenden denselben Click-Ereignishandler, ButtonClicked. Beide Schaltflächen haben einen Namen, btnOK oder btnCancel, der es dem Handler ermöglicht, durch Untersuchen des Argumentwerts sender zu ermitteln, auf welche Schaltfläche geklickt wurde. Der Handler führt die folgenden Aktionen aus:

  • Erstellt ein MyControlEventArgs -Objekt, das die Daten aus den TextBox Elementen enthält.

  • Wenn die benutzende Person auf die Schaltfläche Abbrechen geklickt hat, wird die MyControlEventArgs-Eigenschaft des IsOK-Objekts auf false festgelegt.

  • Er löst das OnButtonClick-Ereignis aus, um dem Host anzuzeigen, dass der Benutzer die Dateneingabe abgeschlossen hat, und übergibt die gesammelten Daten zurück.

Fügen Sie Ihrer Klasse MyControl1 den folgenden Code nach der Init-Methode hinzu.

private void ButtonClicked(object sender, RoutedEventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                        txtName.Text,
                                                        txtAddress.Text,
                                                        txtCity.Text,
                                                        txtState.Text,
                                                        txtZip.Text);
    if (sender == btnCancel)
    {
        retvals.IsOK = false;
    }
    if (OnButtonClick != null)
        OnButtonClick(this, retvals);
}

Erstellen von Eigenschaften

Der Rest der Klasse macht einfach Eigenschaften verfügbar, die den zuvor besprochenen globalen Variablen entsprechen. Wenn sich eine Eigenschaft ändert, passt der festgelegte Accessor das Erscheinungsbild des Steuerelements an, indem er die entsprechenden Elementeigenschaften ändert und die zugrunde liegenden globalen Variablen aktualisiert.

Fügen Sie der Klasse MyControl1 den folgenden Code hinzu.

public FontWeight MyControl_FontWeight
{
    get { return _fontWeight; }
    set
    {
        _fontWeight = value;
        nameLabel.FontWeight = value;
        addressLabel.FontWeight = value;
        cityLabel.FontWeight = value;
        stateLabel.FontWeight = value;
        zipLabel.FontWeight = value;
    }
}
public double MyControl_FontSize
{
    get { return _fontSize; }
    set
    {
        _fontSize = value;
        nameLabel.FontSize = value;
        addressLabel.FontSize = value;
        cityLabel.FontSize = value;
        stateLabel.FontSize = value;
        zipLabel.FontSize = value;
    }
}
public FontStyle MyControl_FontStyle
{
    get { return _fontStyle; }
    set
    {
        _fontStyle = value;
        nameLabel.FontStyle = value;
        addressLabel.FontStyle = value;
        cityLabel.FontStyle = value;
        stateLabel.FontStyle = value;
        zipLabel.FontStyle = value;
    }
}
public FontFamily MyControl_FontFamily
{
    get { return _fontFamily; }
    set
    {
        _fontFamily = value;
        nameLabel.FontFamily = value;
        addressLabel.FontFamily = value;
        cityLabel.FontFamily = value;
        stateLabel.FontFamily = value;
        zipLabel.FontFamily = value;
    }
}

public SolidColorBrush MyControl_Background
{
    get { return _background; }
    set
    {
        _background = value;
        rootElement.Background = value;
    }
}
public SolidColorBrush MyControl_Foreground
{
    get { return _foreground; }
    set
    {
        _foreground = value;
        nameLabel.Foreground = value;
        addressLabel.Foreground = value;
        cityLabel.Foreground = value;
        stateLabel.Foreground = value;
        zipLabel.Foreground = value;
    }
}

Senden der Daten zurück an den Host

Die letzte Komponente in der Datei ist die MyControlEventArgs Klasse, die zum Senden der gesammelten Daten an den Host verwendet wird.

Fügen Sie Ihrem MyControls-Namespace den folgenden Code hinzu. Die Umsetzung ist einfach und wird nicht weiter diskutiert.

public class MyControlEventArgs : EventArgs
{
    private string _Name;
    private string _StreetAddress;
    private string _City;
    private string _State;
    private string _Zip;
    private bool _IsOK;

    public MyControlEventArgs(bool result,
                              string name,
                              string address,
                              string city,
                              string state,
                              string zip)
    {
        _IsOK = result;
        _Name = name;
        _StreetAddress = address;
        _City = city;
        _State = state;
        _Zip = zip;
    }

    public string MyName
    {
        get { return _Name; }
        set { _Name = value; }
    }
    public string MyStreetAddress
    {
        get { return _StreetAddress; }
        set { _StreetAddress = value; }
    }
    public string MyCity
    {
        get { return _City; }
        set { _City = value; }
    }
    public string MyState
    {
        get { return _State; }
        set { _State = value; }
    }
    public string MyZip
    {
        get { return _Zip; }
        set { _Zip = value; }
    }
    public bool IsOK
    {
        get { return _IsOK; }
        set { _IsOK = value; }
    }
}

Erstellen Sie die Lösung. Der Build erzeugt eine DLL mit dem Namen MyControls.dll.

Implementieren der Windows Forms-Hostanwendung

Die Windows Forms-Hostanwendung verwendet ein ElementHost-Objekt zum Hosten des zusammengesetzten WPF-Steuerelements. Die Anwendung verarbeitet das OnButtonClick-Ereignis, um die Daten des zusammengesetzten Steuerelements zu empfangen. Die Anwendung verfügt auch über eine Reihe von Optionsschaltflächen, mit denen Sie die Darstellung des Steuerelements ändern können. Die folgende Abbildung zeigt die Anwendung.

Die folgende Abbildung zeigt ein in einer Windows Forms-Anwendung gehostetes zusammengesetztes WPF-Steuerelement.

Screenshot: Hosten eines Avalon-Steuerelements in Windows Forms

Projekt erstellen

So starten Sie das Projekt:

  1. Starten Sie Visual Studio, und öffnen Sie das Dialogfeld Neues Projekt.

  2. Wählen Sie in Visual C# in der Kategorie „Windows” die Vorlage Windows Forms-Anwendung aus.

  3. Benennen Sie das neue Projekt WFHost.

  4. Geben Sie für den Speicherort denselben Ordner auf oberster Ebene an, der das MyControls-Projekt enthält.

  5. Klicken Sie auf OK, um das Projekt zu erstellen.

Sie müssen auch Verweise auf die DLL, die MyControl1 enthält, und auf andere Assemblys hinzufügen.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und wählen Sie Verweis hinzufügen aus.

  2. Klicken Sie auf die Registerkarte Durchsuchen, und navigieren Sie zu dem Ordner mit „MyControls.dll“. In dieser exemplarischen Vorgehensweise ist dies der Ordner „MyControls\bin\Debug“.

  3. Wählen Sie MyControls.dllaus, und klicken Sie dann auf OK.

  4. Fügen Sie Verweise auf die folgenden Assemblys hinzu.

    • PresentationCore

    • PresentationFramework

    • System.Xaml

    • WindowsBase

    • WindowsFormsIntegration

Implementieren der Benutzeroberfläche für die Anwendung

Die Benutzeroberfläche für die Windows Forms-Anwendung enthält mehrere Steuerelemente, die dazu dienen, mit dem zusammengesetzten WPF-Steuerelement zu interagieren.

  1. Öffnen Sie Formular1 im Windows Form-Designer.

  2. Vergrößern Sie das Formular, um die Steuerelemente aufzunehmen.

  3. Fügen Sie in der oberen rechten Ecke des Formulars ein System.Windows.Forms.Panel-Steuerelement zur Aufbewahrung des zusammengesetzten WPF-Steuerelements hinzu.

  4. Fügen Sie dem Formular die folgenden System.Windows.Forms.GroupBox-Steuerelemente hinzu.

    Name Text
    groupBox1 Hintergrundfarbe
    groupBox2 Vordergrundfarbe
    groupBox3 Schriftgröße
    groupBox4 Schriftfamilie
    groupBox5 Schriftstil
    groupBox6 Schriftstärke
    groupBox7 Daten vom Steuerelement
  5. Fügen Sie die folgenden System.Windows.Forms.RadioButton Steuerelemente zu den System.Windows.Forms.GroupBox-Steuerelementen hinzu.

    GroupBox Name Text
    groupBox1 radioBackgroundOriginal Original
    groupBox1 RadioHintergrundHellgrün Hellgrün
    groupBox1 radioBackgroundHelllachs Helles Lachsrot
    groupBox2 RadioVordergrundOriginal Original
    groupBox2 radioForegroundRed Rot
    groupBox2 RadioVordergrundGelb Gelb
    groupBox3 radioSizeOriginal Original
    groupBox3 radioSizeTen 10
    groupBox3 radioSizeTwelve 12
    groupBox4 radioFamilyOriginal Original
    groupBox4 radioFamilyTimes Zeiten Neurömisch
    groupBox4 radioFamilyWingDings Wingdings
    groupBox5 radioStyleOriginal Normal
    groupBox5 radioStyleItalic Kursiv
    groupBox6 radioWeightOriginal Original
    groupBox6 radioWeightBold Fett
  6. Fügen Sie dem letzten System.Windows.Forms.Label die folgenden System.Windows.Forms.GroupBox-Steuerelemente hinzu. Diese Steuerelemente zeigen die vom zusammengesetzten WPF-Steuerelement zurückgegebenen Daten an.

    GroupBox Name Text
    groupBox7 lblName Name:
    groupBox7 lblAddress Straße und Hausnummer:
    groupBox7 lblCity Stadt:
    groupBox7 lblState Zustand:
    groupBox7 lblZip Postleitzahl:

Initialisieren des Formulars

Sie implementieren den Hostingcode generell im Load-Ereignishandler des Formulars. Der folgende Code zeigt den Load-Ereignishandler, einen Ereignishandler für das WPF-Verbundsteuerelement Loaded und Deklarationen für mehrere globale Variablen, die später verwendet werden.

Doppelklicken Sie im Windows Forms-Designer auf das Formular, um einen Load-Ereignishandler zu erstellen. Fügen Sie am Anfang von „Form1.cs“ die folgenden using-Anweisungen hinzu.

using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Media;

Ersetzen Sie den Inhalt der vorhandenen Form1 Klasse durch den folgenden Code.

private ElementHost ctrlHost;
private MyControls.MyControl1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
System.Windows.Media.FontFamily initFontFamily;

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    ctrlHost = new ElementHost();
    ctrlHost.Dock = DockStyle.Fill;
    panel1.Controls.Add(ctrlHost);
    wpfAddressCtrl = new MyControls.MyControl1();
    wpfAddressCtrl.InitializeComponent();
    ctrlHost.Child = wpfAddressCtrl;

    wpfAddressCtrl.OnButtonClick +=
        new MyControls.MyControl1.MyControlEventHandler(
        avAddressCtrl_OnButtonClick);
    wpfAddressCtrl.Loaded += new RoutedEventHandler(
        avAddressCtrl_Loaded);
}

void avAddressCtrl_Loaded(object sender, EventArgs e)
{
    initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
    initForeBrush = wpfAddressCtrl.MyControl_Foreground;
    initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
    initFontSize = wpfAddressCtrl.MyControl_FontSize;
    initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
    initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}

Die Form1_Load-Methode im vorstehenden Code zeigt die allgemeine Vorgehensweise zum Hosten eines WPF-Steuerelements:

  1. Erstellen Sie ein neues ElementHost-Objekt.

  2. Legen Sie die Dock-Eigenschaft des Steuerelements auf DockStyle.Fill fest.

  3. Fügen Sie das Steuerelement ElementHost der Auflistung Panel des Steuerelements Controls hinzu.

  4. Erstellen Sie eine Instanz des WPF-Steuerelements.

  5. Hosten Sie das zusammengesetzte Steuerelement im Formular, indem Sie es der Eigenschaft ElementHost des Steuerelements Child zuweisen.

Die verbleibenden zwei Zeilen in der Form1_Load-Methode fügen Handler an zwei Steuerelementereignisse an:

  • OnButtonClick ist ein benutzerdefiniertes Ereignis, das von der komplexen Steuerung ausgelöst wird, wenn der Benutzer auf die Schaltfläche OK oder Abbrechen klickt. Sie behandeln das Ereignis, um die Antwort des Benutzers abzurufen und alle Vom Benutzer angegebenen Daten zu sammeln.

  • Loaded ist ein Standardereignis, das von einem WPF-Steuerelement ausgelöst wird, wenn es vollständig geladen ist. Das Ereignis wird hier verwendet, da das Beispiel mehrere globale Variablen mithilfe von Eigenschaften aus dem Steuerelement initialisieren muss. Zum Zeitpunkt des Load-Ereignisses für das Formular ist das Steuerelement nicht vollständig geladen, und diese Werte sind noch auf null festgelegt. Sie müssen warten, bis das Loaded-Ereignis des Steuerelements eintritt, bevor Sie auf diese Eigenschaften zugreifen können.

Der Loaded-Ereignishandler wird im vorhergehenden Code angezeigt. Der OnButtonClick-Handler wird im nächsten Abschnitt erläutert.

Verarbeiten von OnButtonClick

Das OnButtonClick-Ereignis tritt auf, wenn der Benutzer auf die Schaltfläche OK oder Abbrechen klickt.

Der Ereignishandler überprüft das IsOK Feld des Ereignisarguments, um zu bestimmen, auf welche Schaltfläche geklickt wurde. Die lbldata-Variablen entsprechen den weiter oben erläuterten Label-Steuerelementen. Wenn der Benutzer auf die Schaltfläche OK klickt, werden die Daten aus den TextBox-Steuerelementen des Steuerelements dem entsprechenden Label-Steuerelement zugewiesen. Wenn der Benutzer auf Abbrechen klickt, werden die Text-Werte auf die Standardzeichenfolgen festgelegt.

Fügen Sie der Form1-Klasse den folgenden „ButtonClick“-Ereignishandlercode hinzu.

void avAddressCtrl_OnButtonClick(
    object sender,
    MyControls.MyControl1.MyControlEventArgs args)
{
    if (args.IsOK)
    {
        lblAddress.Text = "Street Address: " + args.MyStreetAddress;
        lblCity.Text = "City: " + args.MyCity;
        lblName.Text = "Name: " + args.MyName;
        lblState.Text = "State: " + args.MyState;
        lblZip.Text = "Zip: " + args.MyZip;
    }
    else
    {
        lblAddress.Text = "Street Address: ";
        lblCity.Text = "City: ";
        lblName.Text = "Name: ";
        lblState.Text = "State: ";
        lblZip.Text = "Zip: ";
    }
}

Erstellen Sie die Anwendung, und führen Sie sie aus. Fügen Sie im zusammengesetzten WPF-Steuerelement etwas Text hinzu, und klicken Sie auf OK. Der Text wird in den Beschriftungen angezeigt. Zu diesem Zeitpunkt wurde noch kein Code für die Verarbeitung der Optionsfelder hinzugefügt.

Ändern des Erscheinungsbilds des Steuerelements

Mit den RadioButton-Steuerelementen im Formular kann der Benutzer die Vorder- und Hintergrundfarben des WPF-Kompositsteuerelements sowie verschiedene Schriftarteigenschaften ändern. Die Hintergrundfarbe wird vom Objekt ElementHost verfügbar gemacht. Die verbleibenden Eigenschaften werden als benutzerdefinierte Eigenschaften des Steuerelements verfügbar gemacht.

Doppelklicken Sie auf jedes RadioButton-Steuerelement im Formular, um CheckedChanged-Ereignishandler zu erstellen. Ersetzen Sie die CheckedChanged-Ereignishandler durch den folgenden Code.

private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = initBackBrush;
}

private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}

private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}

private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}

private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}

private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}

private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}

private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("WingDings");
}

private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = initFontSize;
}

private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 10;
}

private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 12;
}

private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}

private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}

private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}

private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}

Erstellen Sie die Anwendung, und führen Sie sie aus. Klicken Sie auf die verschiedenen Optionsfelder, um die Auswirkung auf das zusammengesetzte WPF-Steuerelement zu sehen.

Siehe auch