Freigeben über


Exemplarische Vorgehensweise: Hosten eines Windows Presentation Foundation-Steuerelements in Windows Forms

Aktualisiert: November 2007

Windows Presentation Foundation (WPF) stellt eine umfangreiche Umgebung zum Erstellen von Anwendungen bereit. Wenn Sie allerdings bereits erheblichen Aufwand für Windows Forms-Code betrieben haben, kann es effektiver sein, eine vorhandene Windows Forms-Anwendung mit WPF zu erweitern, anstatt sie von Grund auf neu zu schreiben. Ein häufiges Szenario besteht darin, eine oder mehrere mit WPF implementierte Seiten in die Windows Forms-Anwendung einzubetten.

Diese exemplarische Vorgehensweise führt Sie durch eine Anwendung, die eine WPF-Seite in einer Windows Forms-Anwendung hostet. Die Seite ist eine einfache Dateneingabeanwendung, die in eine DLL gepackt wird. Dieses Beispiel soll in Darstellung und Funktionalität mit Beispiel für das Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation fast identisch sein. Der Hauptunterschied liegt in einer Umkehrung des Hostingszenarios.

Tipp

Die gehostete Seite ist kein WPF-Steuerelement im engeren Sinne des Begriffes. Es handelt sich eher um eine gewöhnliche WPF-Seite, die in eine DLL gepackt wird. Die Techniken zum Hosten eines WPF-Steuerelements in einem Formular entsprechen jedoch denen zum Hosten einer gewöhnlichen Seite. Weitere Informationen zu WPF-Steuerelementen finden Sie unter Anpassung von Steuerelementen.

Die exemplarische Vorgehensweise ist in zwei Abschnitte unterteilt. Im ersten Abschnitt wird kurz die Implementierung der WPF-Seite beschrieben. Im zweiten Abschnitt wird detailliert erläutert, wie die Seite in einer Windows Forms-Anwendung gehostet werden kann, Ereignisse von der Seite empfangen werden können und wie auf einige Eigenschaften der Seite zugegriffen werden kann.

Zu den Aufgaben in dieser exemplarischen Vorgehensweise gehören:

  • Implementieren der Windows Presentation Foundation-Seite.

  • Implementieren der Windows Forms-Hostanwendung.

Eine vollständige Codeauflistung der in dieser exemplarischen Vorgehensweise veranschaulichten Aufgaben finden Sie unter Beispiel für das Hosten eines einfachen Windows Presentation Foundation-Steuerelements in Windows Forms.

Vorbereitungsmaßnahmen

Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie die folgenden Komponenten:

  • Visual Studio 2008.

Implementieren der Windows Presentation Foundation-Seite

Die in diesem Beispiel verwendete WPF-Seite ist ein einfaches Dateneingabeformular, das Namen und Adresse des Benutzers aufnimmt. Wenn der Benutzer auf eine der zwei Schaltflächen klickt, um anzuzeigen, dass die Aufgabe beendet ist, löst die Seite ein benutzerdefiniertes Ereignis aus, um diese Informationen an den Host zurückzugeben. Diese Seite entspricht in Form und Funktion im Wesentlichen dem in Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation verwendeten Windows Forms-Steuerelement. Es gibt keine Besonderheiten auf der Seite, um sie für das Hosten in einem Windows Forms-Formular anzupassen. Sie könnten sie ebenso einfach in einen Frame auf einer größeren WPF-Seite laden. Die folgende Abbildung zeigt die gerenderte Seite.

Windows Presentation Foundation-Seite

Einfaches WPF-Steuerelement

Erstellen des Projekts

So starten Sie das Projekt

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

  2. Wählen Sie die Vorlage WPF-Browseranwendung aus.

  3. Nennen Sie das neue Projekt MyControls, und fügen Sie es einem passend benannten Ordner der obersten Ebene, z. B. WfHostingWpf, hinzu. Später legen Sie auch die Hostanwendung in diesem Ordner ab. Klicken Sie auf OK, um das Projekt zu erstellen. Das Standardprojekt enthält eine einzige Seite mit dem Namen Page1.

  4. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und wählen Sie Eigenschaften aus.

  5. Legen Sie den Ausgabetyp auf Klassenbibliothek fest, um die Seite als DLL zu kompilieren.

  6. Löschen Sie die Anwendungsdefinitionsdateien MyApp.xaml und MyApp.xaml.cs aus dem Projekt. Sie benötigen diese Dateien nur, wenn Sie die Seite als Anwendung implementieren.

Tipp

Wenn Sie eine WPF-Anwendung als Klassenbibliothek kompilieren, können Sie sie nicht aufrufen, um die gerenderte Seite anzuzeigen. Aus diesem Grund ist es möglicherweise besser, als Ausgabetyp "Windows-Anwendung" zu belassen, bis die Anwendung vollständig implementiert ist. Dadurch können Sie die Darstellung der Seiten überprüfen, indem Sie die Anwendung aufrufen. Wenn Sie mit allem zufrieden sind, löschen Sie die Anwendungsdefinitionsdateien, und ändern Sie den Ausgabetyp auf "Klassenbibliothek", um die Anwendung als DLL zu kompilieren.

Das Projekt sollte Verweise auf die folgenden System-DLLs aufweisen. Wenn diese DLLs nicht standardmäßig eingeschlossen sind, fügen Sie sie dem Projekt hinzu.

  • System

  • PresentationCore

  • PresentationFramework

  • WindowsBase

Implementieren der Benutzeroberfläche der Seite

Die Benutzeroberfläche (user interface, UI) der WPF-Seite wird mit Extensible Application Markup Language (XAML) implementiert. Sie soll in Darstellung und Funktionalität dem in Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation erläuterten Windows Forms-Steuerelement ähnlich sein. Die Benutzeroberfläche für die Dateneingabe der Seite besteht aus fünf TextBox-Elementen. Jedes TextBox-Element verfügt über ein zugeordnetes TextBlock-Element, das als Bezeichnung dient. Es gibt zwei Button-Elemente unten auf der Seite: OK und Abbrechen. Wenn der Benutzer auf eine der zwei Schaltflächen klickt, löst die Seite ein benutzerdefiniertes Ereignis aus, um die Informationen an den Host zurückzugeben.

Grundlegendes Layout

Die verschiedenen Benutzeroberfläche-Elemente sind in einem Grid-Element enthalten. Sie können Grid zum Anordnen der Seiteninhalte in ähnlicher Weise wie ein Table-Element in HTML verwenden. WPF verfügt ebenfalls über ein Table-Element, Grid ist jedoch kompakter und für einfache Layoutaufgaben besser geeignet.

Im folgenden Beispiel wird der grundlegende Layoutcode gezeigt. Dieser Code definiert durch Angabe der Anzahl von Spalten und Zeilen im Grid-Element die Gesamtstruktur der Seite. Damit können Sie den Code in Page1.xaml ersetzen.

<Grid xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.Page1"
      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>

Hinzufügen der Elemente TextBlock und TextBox zum Raster

Sie platzieren ein Benutzeroberfläche-Element im Raster, indem Sie das RowProperty-Attribut und das ColumnProperty-Attribut des Elements auf die entsprechende Zeilen- und Spaltennummer festlegen. Denken Sie daran, dass die Zeilen- und Spaltennummerierung nullbasiert ist. Ein Element kann durch Festlegen seines ColumnSpanProperty-Attributs mehrere Spalten überspannen. Weitere Informationen über Grid-Elemente finden Sie unter Gewusst wie: Erstellen eines Elements von Grid.

Im folgenden Beispiel werden das TextBox-Element und das TextBlock-Element der Seite mit dem jeweiligen RowProperty-Attribut und dem ColumnProperty-Attribut gezeigt, die so festgelegt sind, dass die Elemente korrekt im Raster platziert werden. Fügen Sie Page1.xaml diesen Code genau unter dem Grid-Element 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"/>

Formatieren der Benutzeroberflächenelemente

Viele Elemente im Dateneingabeformular ähneln einander, d. h. mehrere ihrer Eigenschaften besitzen identische Einstellungen. Anstatt die Attribute jedes Elements einzeln festzulegen, werden im Beispielcode mithilfe von Style-Elementen standardmäßige Eigenschafteneinstellungen für Elementklassen definiert. Dieser Ansatz reduziert die Komplexität der Seite und ermöglicht es Ihnen, die Darstellung mehrerer Elemente durch ein einziges Stilattribut zu ändern.

Die Style-Elemente sind in der Resources-Eigenschaft des Grid-Elements enthalten, sodass sie von allen Elementen auf der Seite verwendet werden können. Wenn ein Stil benannt ist, wird er auf ein Element angewendet, indem dem Stilnamen ein Style-Elementsatz hinzugefügt wird. Unbenannte Stile werden zum Standardstil für das Element. Weitere Informationen über WPF-Stile finden Sie unter Erstellen von Formaten und Vorlagen.

Im folgenden Beispiel werden die Style-Elemente für die WPF-Seite dargestellt. Fügen Sie Page1.xaml den Code genau unter dem Grid-Element hinzu. Wie die Stile auf Elemente angewendet werden, sehen Sie im vorherigen Codebeispiel. Das letzte TextBlock-Element z. B. hat den inlineText-Stil, und das letzte TextBox-Element verwendet den Standardstil.

<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 auf der Seite sind die Button-Elemente OK und Abbrechen, die die ersten zwei Spalten der letzten Zeile im Grid belegen. Diese Elemente verwenden den allgemeinen Ereignishandler ButtonClicked und den Button-Standardstil, der im vorherigen Codebeispiel definiert wurde. Fügen Sie Page1.xaml den folgenden Code genau unter dem letzten TextBox-Element hinzu. Der XAML-Teil der Seite 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 Code-Behind-Datei der Seite

Die Code-Behind-Datei der WPF-Seite, Page1.xaml.cs, implementiert vier wesentliche Aufgaben:

  1. Registrierung des DLL-Namens der Seite beim Application-Objekt, sodass bekannt ist, woher die Seite geladen werden soll.

  2. Behandlung des Ereignisses, das ausgelöst wird, wenn der Benutzer auf eine der Schaltflächen klickt.

  3. Abrufen der Daten von den TextBox-Elementen und Packen der Daten in ein benutzerdefiniertes Ereignisargumentobjekt.

  4. Auslösen des benutzerdefinierten OnButtonClick-Ereignisses, das den Host benachrichtigt, dass der Benutzer den Vorgang abgeschlossen hat, und das die Daten wieder an den Host übergibt.

Die Seite macht auch eine Reihe von Farb- und Schriftarteigenschaften verfügbar, mit denen die Darstellung der Seite gesteuert werden kann. Im Gegensatz zur WindowsFormsHost-Klasse, die zum Hosten eines Windows Forms-Steuerelements verwendet wird, macht die ElementHost-Klasse nur die Background-Eigenschaft der Seite verfügbar. Um die Ähnlichkeit zwischen diesem Codebeispiel und dem in Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation erläuterten Beispiel beizubehalten, macht die Seite die übrigen Eigenschaften direkt verfügbar.

Grundlegende Struktur der Code-Behind-Datei

Die Code-Behind-Datei besteht aus dem einzelnen Namespace MyControls, der die zwei Klassen Page1 und MyControlEventArgs enthält. Ersetzen Sie den Code in Page1.xaml.cs durch den folgenden Code.

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Media;

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

Die erste Klasse, Page1, ist eine partielle Klasse mit dem Code, der die Funktionen der in Page1.xaml definierten Benutzeroberfläche implementiert. Wenn Page1.xaml analysiert wird, wird XAML in die gleiche partielle Klasse umgewandelt, und die beiden partiellen Klassen werden zusammengeführt, um die kompilierte Seite zu bilden. Daher muss der Klassenname in der Code-Behind-Datei mit dem Page1.xaml zugewiesenen Klassennamen übereinstimmen, und er muss vom Stammelement der Seite erben. Die zweite Klasse, MyControlEventArgs, ist eine Ereignisklasse für Argumente, die verwendet wird, um die Daten an den Host zurückzusenden.

Initialisieren der Page1-Klasse

Im folgenden Codebeispiel werden mehrere grundlegende Aufgaben implementiert:

  • Deklarieren des privaten Ereignisses OnButtonClick und seines zugeordneten Delegaten MyControlEventHandler.

  • Erstellen mehrerer privater globaler Variablen, in denen die Benutzerdaten gespeichert werden. Diese Daten werden durch entsprechende Eigenschaften verfügbar gemacht.

  • Implementieren des Handlers Init für das Loaded-Ereignis der Seite. Dieser Handler initialisiert die globalen Variablen, indem er ihnen die in Page1.xaml definierten Werte zuweist. Dazu verwendet er Name, der dem normalen TextBlock-Element nameLabel zugewiesen ist, um auf die Eigenschafteneinstellungen dieses Elements zuzugreifen.

Fügen Sie der Page1-Klasse den folgenden Code hinzu.

public partial class Page1 : Grid
{
    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;
    }

Behandeln der Klickereignisse der Schaltflächen

Der Benutzer zeigt durch Klicken auf die Schaltfläche OK oder Abbrechen unten auf der Seite an, dass er die Dateneingabe abgeschlossen hat. Beide Schaltflächen verwenden denselben Click-Ereignishandler, ButtonClicked. Beide Schaltflächen besitzen einen Namen, btnOK bzw. btnFalse, mit denen der Handler durch Überprüfen des Werts des sender-Arguments feststellen kann, auf welche Schaltfläche geklickt wurde. Der Handler führt folgende Aufgaben aus:

  • Erstellen eines MyControlEventArgs-Objekts, das die Daten der TextBox-Elemente der Seite enthält.

  • Festlegen der IsOK-Eigenschaft des MyControlEventArgs-Objekts auf false, wenn der Benutzer auf die Schaltfläche Abbrechen geklickt hat.

  • Auslösen des OnButtonClick-Ereignisses, um dem Host anzuzeigen, dass der Benutzer den Vorgang abgeschlossen hat, und Übergabe der gesammelten Daten.

Fügen Sie der Page1-Klasse den folgenden Code unter 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 globalen Variablen entsprechen, die oben erläutert wurden. Wenn sich eine Eigenschaft ändert, ändert der set-Accessor die Darstellung der Seite, indem er die entsprechenden Elementeigenschaften ändert und die zugrunde liegenden globalen Variablen aktualisiert.

Fügen Sie der Page1-Klasse 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;
    }
}

Zurücksenden der Daten an den Host

Die letzte Komponente in der Datei ist die MyControlEventArgs-Klasse, die verwendet wird, um die gesammelten Daten zurück an den Host zu senden. Fügen Sie dem MyControls-Namespace den folgenden Code hinzu. Die Implementierung ist einfach und wird nicht weiter erläutert.

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

Implementieren der Windows Forms-Hostanwendung

Die Windows Forms-Hostanwendung verwendet ein ElementHost-Objekt, um die WPF-Seite im Formular zu hosten. Die Anwendung behandelt das OnButtonClick-Ereignis der Seite, um die Daten vom Formular zu empfangen. Die Anwendung verfügt auch über eine Reihe von Optionsfeldern, mit denen Sie die Seitendarstellung ändern können. In der folgenden Bildschirmabbildung wird das gerenderte Formular dargestellt.

In einer Windows Forms-Anwendung gehostete Windows Presentation Foundation-Seite

Windows Forms Hosting Avalon-Steuerelement

Erstellen des Projekts

So starten Sie das Projekt

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

  2. Wählen Sie C#-Projekte mit der Vorlage Windows Forms-Anwendung aus.

  3. Nennen Sie das neue Projekt WFHost, und fügen Sie es demselben Ordner der obersten Ebene hinzu, der das Projekt MyControls enthält. Klicken Sie auf OK, um das Projekt zu erstellen.

Sie müssen auch einen Verweis auf die DLL hinzufügen, die die WPF-Seite enthält:

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

  2. Klicken Sie auf die Registerkarte Durchsuchen, und navigieren Sie zum Ordner, der MyControls.dll enthält.

  3. Wählen Sie MyControls.dll aus, und klicken Sie auf OK, um der Verweisliste die DLL hinzuzufügen.

  4. Fügen Sie im Projektmappen-Explorer einen Verweis auf die WindowsFormsIntegration-Assembly mit dem Namen WindowsFormsIntegration.dll hinzu.

Implementieren der Benutzeroberfläche für das Formular

Öffnen Sie den Windows Forms-Designer, und erstellen Sie das Layout für das Formular anhand der Abbildung in Implementieren der Windows Forms-Hostanwendung:

  1. Erweitern Sie das Standardformular, um die Steuerelemente und die WPF-Seite ordnungsgemäß anzuzeigen.

  2. Fügen Sie in der rechten oberen Ecke des Formulars ein System.Windows.Forms.Panel-Steuerelement für die WPF-Seite hinzu.

  3. Fügen Sie sechs Sätze von System.Windows.Forms.RadioButton-Steuerelementen hinzu, wie in der Abbildung gezeigt.

  4. Fügen Sie in der rechten unteren Ecke des Formulars fünf System.Windows.Forms.Label-Steuerelemente hinzu, wie in der Abbildung gezeigt. Diese Steuerelemente dienen als Bezeichnungen für die vom WPF-Steuerelement zurückgegebenen Daten.

  5. Fügen Sie ein Label-Steuerelement rechts von jedem im vorherigen Schritt hinzugefügten Label-Steuerelement hinzu. Legen Sie die Text-Eigenschaft von jedem Steuerelement auf "" fest. Diese Steuerelemente zeigen die vom WPF-Steuerelement zurückgegebenen Daten an.

  6. Fügen Sie ein weiteres Label-Steuerelement hinzu, das als Titel für die Gruppe von Steuerelementen aus den zwei letzten Schritten dient. Da diese Label als Titel für die Gruppe dienen soll, vergrößern Sie die Schriftart um zwei Punkte gegenüber den Steuerelementen in der Gruppe.

Initialisieren des Formulars

Hostcode wird üblicherweise im Load-Ereignishandler des Formulars implementiert. Doppelklicken Sie im Windows Forms-Designer auf das Formular, um eine Load-Ereignishandlermethode zu erstellen. Das folgende Codebeispiel enthält den Load-Ereignishandler des Beispiels, einen Handler für das Loaded-Ereignis der WPF-Seite und Deklarationen für mehrere globale Variablen, die später verwendet werden. Ersetzen Sie den Code in Form1.cs durch den folgenden Code.

partial class Form1 : Form
{
    private ElementHost ctrlHost;
    private MyControls.Page1 wpfAddressCtrl;
    System.Windows.FontWeight initFontWeight;
    double initFontSize;
    System.Windows.FontStyle initFontStyle;
    System.Windows.Media.SolidColorBrush initBackBrush;
    System.Windows.Media.SolidColorBrush initForeBrush;
    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.Page1();
        wpfAddressCtrl.InitializeComponent();
        ctrlHost.Child = wpfAddressCtrl;

        wpfAddressCtrl.OnButtonClick += 
            new MyControls.Page1.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 vorangehenden Codebeispiel zeigt das allgemeine Verfahren 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 ElementHost-Steuerelement der Controls-Auflistung des Panel-Steuerelements hinzu.

  4. Erstellen Sie eine Instanz der WPF-Seite.

  5. Hosten Sie die Seite im Formular, indem Sie die Seite der Child-Eigenschaft des ElementHost-Steuerelements zuweisen.

Die übrigen zwei Zeilen in der Form1_Load-Methode fügen Handler an zwei Seitenereignisse an:

  • OnButtonClick ist ein benutzerdefiniertes Ereignis, das von der Seite ausgelöst wird, wenn der Benutzer auf die Schaltfläche OK oder Abbrechen klickt. Das Ereignis wird behandelt, um die Antwort des Benutzers abzurufen und die vom Benutzer eingegebenen Daten zu sammeln.

  • Loaded ist ein Standardereignis, das von einer WPF-Seite ausgelöst wird, wenn sie vollständig geladen wurde. Hier wird das Ereignis verwendet, da im Beispiel mehrere globale Variablen, die Eigenschaften der Seite verwenden, initialisiert werden müssen. Zum Zeitpunkt des Load-Ereignisses des Formulars ist die Seite nicht vollständig geladen, und diese Werte sind immer noch auf null festgelegt. Sie müssen bis zum Loaded-Ereignis der Seite warten, bevor Sie auf diese Eigenschaften zugreifen können.

Der Loaded-Ereignishandler wird im vorangehenden Codebeispiel gezeigt. Der OnButtonClick-Handler wird im nächsten Abschnitt erläutert.

Behandeln von OnButtonClick

Das OnButtonClick-Ereignis tritt ein, 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 nicht sichtbaren Label-Steuerelementen, die früher erläutert wurden. Wenn der Benutzer auf die Schaltfläche OK geklickt hat, werden die Daten der TextBox-Steuerelemente der Seite dem entsprechenden Label-Steuerelement zugewiesen. Wenn der Benutzer auf Abbrechen geklickt hat, werden die Text-Werte auf null festgelegt.

Fügen Sie Form1.cs den folgenden Code hinzu. Sie können die Anwendung jetzt kompilieren und ausführen.

void avAddressCtrl_OnButtonClick(
    object sender, 
    MyControls.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: ";
    }
}

Ändern der Darstellung der Windows Presentation Foundation-Seite

Mit den RadioButton-Steuerelementen auf der linken Seite des Formulars kann der Benutzer die Vorder- und Hintergrundfarben der WPF-Seite und einige Schriftarteigenschaften ändern. Die Hintergrundfarbe wird durch das ElementHost-Objekt verfügbar gemacht. Die übrigen Eigenschaften werden als benutzerdefinierte Eigenschaften der Seite verfügbar gemacht.

Doppelklicken Sie auf die RadioButton-Steuerelemente im Formular, um Vorlagen für die entsprechenden CheckedChanged-Ereignishandler zu erstellen. Extrahieren Sie den Code aus den folgenden Handlern, und fügen Sie ihn den entsprechenden Handlern in Form1.cs hinzu.

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 FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new 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;
}

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Presentation Foundation-Steuerelements in Windows Forms

Konzepte

Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation

Referenz

ElementHost

WindowsFormsHost

Weitere Ressourcen

WPF-Designer