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

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, zumindest einen Teil dieses Codes in Ihrer WPF-Anwendung wieder zu verwenden, anstatt ihn von Grund auf neu zu schreiben. Das häufigste Szenario ist, dass Sie über vorhandene benutzerdefinierte Windows Forms-Steuerelemente verfügen. In einigen Fällen haben Sie möglicherweise noch nicht einmal Zugriff auf den Quellcode für diese Steuerelemente. WPF stellt ein einfaches Verfahren bereit, um diese Steuerelemente in einer WPF-Anwendung zu hosten. Zum Beispiel können Sie WPF für den Großteil der Programmierung verwenden, während sie die spezialisierten System.Windows.Forms.DataGridView-Steuerelemente hosten.

Diese exemplarische Vorgehensweise führt Sie durch eine Anwendung, die ein zusammengesetztes Windows Forms-Steuerelement auf einer WPF-Seite hostet. Diese allgemeine Prozedur kann auf komplexere Anwendungen und Steuerelemente erweitert werden.

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

In dieser exemplarischen Vorgehensweise werden folgende Aufgaben veranschaulicht:

  • Implementieren des Windows Forms-Steuerelements.

  • Implementieren der Hostanwendung mit Windows Presentation Foundation.

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

Vorbereitungsmaßnahmen

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

  • Visual Studio 2008.

Implementieren des Windows Forms-Steuerelements

Das in diesem Beispiel verwendete Windows Forms-Steuerelement ist ein einfaches Dateneingabeformular. Dieses Formular nimmt den Namen und die Adresse des Benutzers auf und verwendet dann ein benutzerdefiniertes Ereignis, um diese Informationen an den Host zurückzugeben. Die folgende Abbildung zeigt das gerenderte Steuerelement.

Windows Forms-Steuerelement

Einfaches Windows Forms-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 C#-Projekte mit der Vorlage Windows Forms-Steuerelementbibliothek aus.

  3. Nennen Sie das neue Projekt MyControls, und klicken Sie auf OK, um das Projekt zu erstellen. Das Standardprojekt enthält ein einzelnes Steuerelement mit dem Namen UserControl1.

  4. Ändern Sie den Namen von UserControl1 in MyControl1.

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

  • System.Data

  • System.Drawing

  • System.Windows.Forms

  • System.XML

Einfügen von Steuerelementen in das Formular

So fügen Sie dem Formular Steuerelemente hinzu

  • Öffnen Sie den Designer für MyControl1.

Platzieren Sie sechs System.Windows.Forms.Label-Steuerelemente und ihre entsprechenden System.Windows.Forms.TextBox-Steuerelemente im Formular, und passen Sie ihre Größe und Anordnung wie in der vorhergehenden Abbildung an. Im Beispiel werden die TextBox-Steuerelemente folgendermaßen benannt:

  • txtName

  • txtAddress

  • txtCity

  • txtState

  • txtZip

Fügen Sie zwei System.Windows.Forms.Button-Steuerelemente mit den Bezeichnungen OK und Cancel hinzu. Im Beispiel lauten die Schaltflächennamen btnOK bzw. btnCancel.

Implementieren des unterstützenden Codes

Öffnen Sie die Codeansicht des Formulars. Das Steuerelement gibt die gesammelten Daten an seinen Host zurück, indem es das benutzerdefinierte OnButtonClick-Ereignis auslöst. Die Daten sind im Ereignisargumentobjekt enthalten. Das folgende Codebeispiel veranschaulicht die Ereignis- und Delegatdeklaration. Fügen Sie diesen Code unter dem vom Designer generierten Code der Codedatei hinzu.

Public Delegate Sub MyControlEventHandler(ByVal sender As Object, ByVal args As MyControlEventArgs)
Public Event OnButtonClick As MyControlEventHandler
public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;

Die MyControlEventArgs-Klasse enthält die Informationen, die an den Host zurückgegeben werden sollen. Fügen Sie dem Namespace des Formulars folgende Klasse hinzu.

Public Class MyControlEventArgs
    Inherits EventArgs
    Private _Name As String
    Private _StreetAddress As String
    Private _City As String
    Private _State As String
    Private _Zip As String
    Private _IsOK As Boolean


    Public Sub New(ByVal result As Boolean, ByVal name As String, ByVal address As String, ByVal city As String, ByVal state As String, ByVal zip As String) 
        _IsOK = result
        _Name = name
        _StreetAddress = address
        _City = city
        _State = state
        _Zip = zip

    End Sub


    Public Property MyName() As String 
        Get
            Return _Name
        End Get
        Set
            _Name = value
        End Set
    End Property

    Public Property MyStreetAddress() As String 
        Get
            Return _StreetAddress
        End Get
        Set
            _StreetAddress = value
        End Set
    End Property

    Public Property MyCity() As String 
        Get
            Return _City
        End Get
        Set
            _City = value
        End Set
    End Property

    Public Property MyState() As String 
        Get
            Return _State
        End Get
        Set
            _State = value
        End Set
    End Property

    Public Property MyZip() As String 
        Get
            Return _Zip
        End Get
        Set
            _Zip = value
        End Set
    End Property

    Public Property IsOK() As Boolean 
        Get
            Return _IsOK
        End Get
        Set
            _IsOK = value
        End Set
    End Property
End Class
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; }
    }
}

Wenn der Benutzer auf die Schaltfläche OK oder Cancel klickt, erstellen die Control.Click-Ereignishandler ein MyControlEventArgs-Objekt, das die Daten enthält und das OnButtonClick-Ereignis auslöst. Der einzige Unterschied zwischen den zwei Handlern ist die IsOK-Eigenschaft des Ereignisarguments. Diese Eigenschaft ermöglicht es dem Host, zu bestimmen, auf welche Schaltfläche geklickt wurde. Sie ist für die Schaltfläche OK auf true und für die Schaltfläche Cancel auf false festgelegt. Das folgende Codebeispiel zeigt die beiden Schaltflächenhandler. Fügen Sie der Klasse diesen Code hinzu, und platzieren Sie ihn unter die im ersten Codebeispiel dieses Abschnitts dargestellte Ereignis- und Delegatdeklaration.

    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOK.Click

        Dim retvals As New MyControlEventArgs(True, txtName.Text, txtAddress.Text, txtCity.Text, txtState.Text, txtZip.Text)
        RaiseEvent OnButtonClick(Me, retvals)

    End Sub


    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        Dim retvals As New MyControlEventArgs(False, txtName.Text, txtAddress.Text, txtCity.Text, txtState.Text, txtZip.Text)
        RaiseEvent OnButtonClick(Me, retvals)

    End Sub
End Class
private void OKButton_Click(object sender, System.EventArgs e)
{

    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                         txtName.Text,
                                                         txtAddress.Text,
                                                         txtCity.Text,
                                                         txtState.Text,
                                                         txtZip.Text);
    OnButtonClick(this, retvals);
}

private void CancelButton_Click(object sender, System.EventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(false,
                                                         txtName.Text,
                                                         txtAddress.Text,
                                                         txtCity.Text,
                                                         txtState.Text,
                                                         txtZip.Text);
    OnButtonClick(this, retvals);
}

Vergeben eines starken Namens für die Assembly und Erstellen der Assembly

Damit von einer WPF-Anwendung auf diese Assembly verwiesen wird, muss sie einen starken Namen haben. Erstellen Sie für einen starken Namen eine Schlüsseldatei mit Sn.exe, und fügen Sie sie der Datei AssemblyInfo.cs des Projekts hinzu.

  1. Öffnen Sie eine Visual Studio-Eingabeaufforderung. Klicken Sie dazu auf das Startmenü, und wählen Sie dann Alle Programme/Microsoft Visual Studio 2008/Visual Studio Tools/Visual Studio 2008 Command Prompt. Dies startet ein Konsolenfenster mit benutzerdefinierten Umgebungsvariablen.

  2. Verwenden Sie an der Eingabeaufforderung den "cd"-Befehl, um zum Projektordner zu wechseln.

  3. Generieren Sie eine Schlüsseldatei mit dem Namen MyControls.snk, indem Sie den folgenden Befehl ausführen.

    Sn.exe -k MyControls.snk
    
  4. Um die Schlüsseldatei in das Projekt aufzunehmen, klicken Sie mit der rechten Maustaste im Projektmappen-Explorer auf den Projektnamen, und öffnen Sie das Dialogfeld Eigenschaften. Wählen Sie die Registerkarte Signierung aus, und geben Sie den Namen der Schlüsseldatei ein.

  5. Erstellen Sie die Assembly. Der Build erzeugt eine DLL mit dem Namen MyControls.dll.

Implementieren der Hostanwendung mit Windows Presentation Foundation

Die WPF-Hostanwendung verwendet das WindowsFormsHost-Steuerelement, um MyControl1 zu hosten. Die Anwendung behandelt das OnButtonClick-Ereignis, um die Daten vom Steuerelement zu empfangen. Sie besitzt außerdem eine Auflistung von Optionsschaltflächen, mit denen Sie einige der Eigenschaften des Steuerelements von der WPF-Seite ändern können. Die folgende Abbildung zeigt die fertige Anwendung.

Die vollständige Anwendung mit dem Steuerelement, das in die Windows Presentation Foundation-Seite eingebettet ist

Ein in einer WPF-Seite eingebettetes Steuerelement

Erstellen des Projekts

So starten Sie das Projekt

  1. Öffnen Sie Visual Studio, und wählen Sie Neues Projekt aus.

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

  3. Nennen Sie das Projekt WpfHost, und klicken Sie auf OK, um das Projekt zu öffnen.

Sie müssen auch einen Verweis auf die DLL hinzufügen, die MyControl1 enthält. Der Verweis lässt sich am einfachsten auf die folgende Weise hinzufügen.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und öffnen Sie das Dialogfeld Verweis hinzufügen.

  2. Klicken Sie auf die Registerkarte Durchsuchen, und wechseln Sie zum Ausgabeordner des Windows Form-Steuerelements. Für dieses Beispiel ist das der Ordner MyControls\bin\Debug.

  3. Wählen Sie die DLL aus, die das Steuerelement enthält, und klicken Sie auf OK, um es zur Verweisliste hinzuzufügen. Für Beispiel für das Hosten eines zusammengesetzten Windows Forms-Steuerelements in Windows Presentation Foundation wird diese DLL MyControls.dll genannt.

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

Implementieren des grundlegenden Layouts

Die Benutzeroberfläche (user interface, UI) der Hostanwendung wird in Page1.xaml implementiert. Diese Datei enthält Extensible Application Markup Language (XAML)-Markup, das das Seitenlayout definiert, und hostet das Windows Forms-Steuerelement. Die Seite wird in drei Bereiche unterteilt:

  • Bereich Steuerelementeigenschaften, der eine Auflistung von Optionsschaltflächen enthält, mit denen Sie verschiedene Eigenschaften des gehosteten Steuerelements ändern können.

  • Bereich Steuerelementdaten, der verschiedene TextBlock-Elemente enthält, die die vom gehosteten Steuerelement zurückgegebenen Daten anzeigen.

  • Das gehostete Steuerelement selbst.

Der Code für das grundlegende Layout wird im folgenden Codebeispiel gezeigt. Der Markupcode, der zum Hosten von MyControl1 benötigt wird, ist in diesem Beispiel nicht enthalten, wird aber später erläutert. Ersetzen Sie den Code in Page1.xaml durch folgenden Code:

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">
  <DockPanel>
    <DockPanel.Resources>
      <Style x:Key="inlineText" TargetType="{x:Type Inline}">
        <Setter Property="FontWeight" Value="Normal"/>
      </Style>
      <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
        <Setter Property="DockPanel.Dock" Value="Top"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Margin" Value="10,5,10,0"/>
      </Style>
    </DockPanel.Resources>

    <StackPanel Orientation="Vertical"
                DockPanel.Dock="Left"
                Background="Bisque"
                Width="250">

      <TextBlock  Margin="10,10,10,10"
                  FontWeight="Bold"
                  FontSize="12">Control Properties</TextBlock>
      <TextBlock Style="{StaticResource titleText}">Background Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalBackColor"
                    IsChecked="True"
                    Click="BackColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnBackGreen"
                    Click="BackColorChanged">LightGreen</RadioButton>
        <RadioButton Name="rdbtnBackSalmon"
                    Click="BackColorChanged">LightSalmon</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Foreground Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalForeColor"
                    IsChecked="True"
                    Click="ForeColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnForeRed"
                    Click="ForeColorChanged">Red</RadioButton>
        <RadioButton Name="rdbtnForeYellow"
                    Click="ForeColorChanged">Yellow</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Family</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalFamily"
                     IsChecked="True"
                    Click="FontChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTimes"
                    Click="FontChanged">Times New Roman</RadioButton>
        <RadioButton Name="rdbtnWingdings"
                    Click="FontChanged">Wingdings</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Size</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalSize"
                    IsChecked="True"
                    Click="FontSizeChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTen"
                    Click="FontSizeChanged">10</RadioButton>
        <RadioButton Name="rdbtnTwelve"
                    Click="FontSizeChanged">12</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Style</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnNormalStyle"
                     IsChecked="True"
                     Click="StyleChanged">Original</RadioButton>
        <RadioButton Name="rdbtnItalic"
                     Click="StyleChanged">Italic</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Weight</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalWeight"
                     IsChecked="True"
                   Click="WeightChanged">
          Original
        </RadioButton>
        <RadioButton Name="rdbtnBold"
                   Click="WeightChanged">Bold</RadioButton>
      </StackPanel>
    </StackPanel>

    <WindowsFormsHost Name="wfh"
                     DockPanel.Dock="Top"
                     Height="300">
      <mcl:MyControl1 Name="mc"/>
    </WindowsFormsHost>

    <StackPanel Orientation="Vertical"
                Height="Auto"
                Background="LightBlue">
      <TextBlock Margin="10,10,10,10"
            FontWeight="Bold"
            FontSize="12">Data From Control</TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Street Address: <Span Name="txtAddress" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        City: <Span Name="txtCity" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        State: <Span Name="txtState" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Zip: <Span Name="txtZip" Style="{StaticResource inlineText}"/>
      </TextBlock>
    </StackPanel>
  </DockPanel>
</Page>
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WpfHost.Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">
  <DockPanel>
    <DockPanel.Resources>
      <Style x:Key="inlineText" TargetType="{x:Type Inline}">
        <Setter Property="FontWeight" Value="Normal"/>
      </Style>
      <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
        <Setter Property="DockPanel.Dock" Value="Top"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Margin" Value="10,5,10,0"/>
      </Style>
    </DockPanel.Resources>

    <StackPanel Orientation="Vertical"
                DockPanel.Dock="Left"
                Background="Bisque"
                Width="250">

      <TextBlock  Margin="10,10,10,10"
                  FontWeight="Bold"
                  FontSize="12">Control Properties</TextBlock>
      <TextBlock Style="{StaticResource titleText}">Background Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalBackColor"
                    IsChecked="True"
                    Click="BackColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnBackGreen"
                    Click="BackColorChanged">LightGreen</RadioButton>
        <RadioButton Name="rdbtnBackSalmon"
                    Click="BackColorChanged">LightSalmon</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Foreground Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalForeColor"
                    IsChecked="True"
                    Click="ForeColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnForeRed"
                    Click="ForeColorChanged">Red</RadioButton>
        <RadioButton Name="rdbtnForeYellow"
                    Click="ForeColorChanged">Yellow</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Family</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalFamily"
                     IsChecked="True"
                    Click="FontChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTimes"
                    Click="FontChanged">Times New Roman</RadioButton>
        <RadioButton Name="rdbtnWingdings"
                    Click="FontChanged">Wingdings</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Size</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalSize"
                    IsChecked="True"
                    Click="FontSizeChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTen"
                    Click="FontSizeChanged">10</RadioButton>
        <RadioButton Name="rdbtnTwelve"
                    Click="FontSizeChanged">12</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Style</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnNormalStyle"
                     IsChecked="True"
                     Click="StyleChanged">Original</RadioButton>
        <RadioButton Name="rdbtnItalic"
                     Click="StyleChanged">Italic</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Weight</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalWeight"
                     IsChecked="True"
                   Click="WeightChanged">
          Original
        </RadioButton>
        <RadioButton Name="rdbtnBold"
                   Click="WeightChanged">Bold</RadioButton>
      </StackPanel>
    </StackPanel>

    <WindowsFormsHost Name="wfh"
                     DockPanel.Dock="Top"
                     Height="300">
      <mcl:MyControl1 Name="mc"/>
    </WindowsFormsHost>

    <StackPanel Orientation="Vertical"
                Height="Auto"
                Background="LightBlue">
      <TextBlock Margin="10,10,10,10"
            FontWeight="Bold"
            FontSize="12">Data From Control</TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Street Address: <Span Name="txtAddress" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        City: <Span Name="txtCity" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        State: <Span Name="txtState" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Zip: <Span Name="txtZip" Style="{StaticResource inlineText}"/>
      </TextBlock>
    </StackPanel>
  </DockPanel>
</Page>

Das erste StackPanel-Element enthält verschieden Gruppen von RadioButton-Steuerelementen, mit denen Sie verschiedene Standardeigenschaften des gehosteten Steuerelements ändern können. Dem folgt ein WindowsFormsHost-Element, das MyControl1 hostet. Das letzte StackPanel-Element enthält verschiedene TextBlock-Elemente, die die vom gehosteten Steuerelement zurückgegebenen Daten anzeigen. Durch die Reihenfolge der Elemente und die Attributeinstellungen Dock und Height wird das gehostete Steuerelement ohne Lücken oder Verzerrungen in die Seite eingebettet.

Hosten des Steuerelements

Der Schwerpunkt der folgenden bearbeiteten Version des vorherigen Codebeispiels liegt auf den Elementen, die zum Hosten von MyControl1 benötigt werden.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">


...


<WindowsFormsHost Name="wfh"
                 DockPanel.Dock="Top"
                 Height="300">
  <mcl:MyControl1 Name="mc"/>
</WindowsFormsHost>
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WpfHost.Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">


...


<WindowsFormsHost Name="wfh"
                 DockPanel.Dock="Top"
                 Height="300">
  <mcl:MyControl1 Name="mc"/>
</WindowsFormsHost>

Das xmlns-Namespace-Zuordnungsattribut erstellt einen Verweis auf den MyControls-Namespace, der das gehostete Steuerelement enthält. Diese Zuordnung ermöglicht es Ihnen, MyControl1 als <mcl:MyControl1> in XAML darzustellen.

Zwei Elemente im Codebeispiel behandeln das Hosting:

  • WindowsFormsHost stellt das WindowsFormsHost-Element dar, das es Ihnen ermöglicht, ein Windows Forms-Steuerelement auf einer WPF-Seite zu hosten.

  • mcl:MyControl1, das MyControl1 darstellt, wird der untergeordneten Auflistung des WindowsFormsHost-Elements hinzugefügt. Dadurch wird dieses Windows Forms-Steuerelement als Teil der WPF-Seite gerendert, und Sie können über die Seite Daten mit dem Steuerelement austauschen.

Implementieren der Code-Behind-Datei

Die Code-Behind-Datei, Page1.xaml.cs, enthält den prozeduralen Code, der die Funktionalität der im vorherigen Abschnitt erläuterten Benutzeroberfläche implementiert. Die Hauptaufgaben sind:

  • Anfügen eines Ereignishandlers an das OnButtonClick-Ereignis von MyControl1.

  • Ändern verschiedener Eigenschaften von MyControl1 auf Grundlage der Auflistung von Optionsschaltflächen.

  • Anzeigen der vom Steuerelement gesammelten Daten.

Initialisieren der Anwendung

Der Code für die Initialisierung ist in einem Ereignishandler für das Loaded-Ereignis der Seite enthalten und fügt einen Ereignishandler an das OnButtonClick-Ereignis des Steuerelements an. Kopieren Sie den folgenden Code in die Page1-Klasse in Page1.xaml.cs.

Class Page1
    Inherits Page

    Private app As Application
    Private myWindow As NavigationWindow
    Private initFontWeight As FontWeight
    Private initFontSize As [Double]
    Private initFontStyle As FontStyle
    Private initBackBrush As SolidColorBrush
    Private initForeBrush As SolidColorBrush
    Private initFontFamily As FontFamily
    Private UIIsReady As Boolean = False


    Private Sub Init(ByVal sender As Object, ByVal e As RoutedEventArgs)
        app = System.Windows.Application.Current
        myWindow = CType(app.MainWindow, NavigationWindow)
        myWindow.SizeToContent = SizeToContent.WidthAndHeight
        wfh.TabIndex = 10
        initFontSize = wfh.FontSize
        initFontWeight = wfh.FontWeight
        initFontFamily = wfh.FontFamily
        initFontStyle = wfh.FontStyle
        initBackBrush = CType(wfh.Background, SolidColorBrush)
        initForeBrush = CType(wfh.Foreground, SolidColorBrush)

        Dim mc As MyControl1 = wfh.Child

        AddHandler mc.OnButtonClick, AddressOf Pane1_OnButtonClick 
        UIIsReady = True

    End Sub
public partial class Page1 : Page
{
    private Application app;
    private NavigationWindow myWindow;
    FontWeight initFontWeight;
    Double initFontSize;
    FontStyle initFontStyle;
    SolidColorBrush initBackBrush;
    SolidColorBrush initForeBrush;
    FontFamily initFontFamily;
    bool UIIsReady = false;

    private void Init(object sender, EventArgs e)
    {
        app = System.Windows.Application.Current;
        myWindow = (NavigationWindow)app.MainWindow;
        myWindow.SizeToContent = SizeToContent.WidthAndHeight;
        wfh.TabIndex = 10;
        initFontSize = wfh.FontSize;
        initFontWeight = wfh.FontWeight;
        initFontFamily = wfh.FontFamily;
        initFontStyle = wfh.FontStyle;
        initBackBrush = (SolidColorBrush)wfh.Background;
        initForeBrush = (SolidColorBrush)wfh.Foreground;
        (wfh.Child as MyControl1).OnButtonClick += new MyControl1.MyControlEventHandler(Pane1_OnButtonClick);
        UIIsReady = true;
    }

Da der vorher erläuterte XAML-Code der Auflistung des untergeordneten Elements des WindowsFormsHost-Elements MyControl1 hinzugefügt hat, können Sie das Child des WindowsFormsHost-Elements umwandeln, um den Verweis auf MyControl1 zu erhalten. Sie können dann diesen Verweis verwenden, um einen Ereignishandler an OnButtonClick anzufügen.

WindowsFormsHost stellt nicht nur einen Verweis auf das Steuerelement selbst bereit, sondern macht eine Reihe von Eigenschaften des Steuerelements verfügbar, die Sie von der Seite aus ändern können. Im Initialisierungscode werden diese Werte privaten globalen Variablen zur späteren Verwendung in der Anwendung zugewiesen.

Behandeln des OnButtonClick-Ereignisses

MyControl1 löst das OnButtonClick-Ereignis aus, wenn der Benutzer auf eine der Schaltflächen des Steuerelements klickt. Fügen Sie der Page1-Klasse folgenden Code hinzu.

    'Handle button clicks on the Windows Form control
    Private Sub Pane1_OnButtonClick(ByVal sender As Object, ByVal args As MyControlEventArgs) 
        txtName.Inlines.Clear()
        txtAddress.Inlines.Clear()
        txtCity.Inlines.Clear()
        txtState.Inlines.Clear()
        txtZip.Inlines.Clear()

        If args.IsOK Then
            txtName.Inlines.Add(" " + args.MyName)
            txtAddress.Inlines.Add(" " + args.MyStreetAddress)
            txtCity.Inlines.Add(" " + args.MyCity)
            txtState.Inlines.Add(" " + args.MyState)
            txtZip.Inlines.Add(" " + args.MyZip)
        End If

    End Sub
End Class
//Handle button clicks on the Windows Form control
private void Pane1_OnButtonClick(object sender, MyControlEventArgs args)
{
    txtName.Inlines.Clear();
    txtAddress.Inlines.Clear();
    txtCity.Inlines.Clear();
    txtState.Inlines.Clear();
    txtZip.Inlines.Clear();

    if (args.IsOK)
    {
        txtName.Inlines.Add( " " + args.MyName );
        txtAddress.Inlines.Add( " " + args.MyStreetAddress );
        txtCity.Inlines.Add( " " + args.MyCity );
        txtState.Inlines.Add( " " + args.MyState );
        txtZip.Inlines.Add( " " + args.MyZip );
    }
}

Die Daten in den Textfeldern werden in das MyControlEventArgs-Objekt gepackt. Wenn der Benutzer auf die Schaltfläche OK klickt, extrahiert der Ereignishandler die Daten und zeigt sie im Bereich unter MyControl1 an.

Ändern der Eigenschaften des Steuerelements

Das WindowsFormsHost-Element macht mehrere Standardeigenschaften des gehosteten Steuerelements verfügbar. Daher können Sie die Darstellung des Steuerelements so ändern, dass es eher dem Stil Ihrer Seite entspricht. Die Gruppen von Optionsschaltflächen im linken Bereich ermöglichen die Änderung mehrerer Farb- und Schrifteigenschaften. Jede Schaltflächengruppe besitzt einen Handler für das Click-Ereignis, der die vom Benutzer ausgewählten Optionsschaltflächen ermittelt und die entsprechende Eigenschaft für das Steuerelement ändert. Kopieren Sie den folgenden Code in die Page1-Klasse. Sie können die Anwendung jetzt kompilieren und ausführen.

Private Sub BackColorChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)

    If sender.Equals(rdbtnBackGreen) Then
        wfh.Background = New SolidColorBrush(Colors.LightGreen)
    ElseIf sender.Equals(rdbtnBackSalmon) Then
        wfh.Background = New SolidColorBrush(Colors.LightSalmon)
    ElseIf UIIsReady = True Then
        wfh.Background = initBackBrush
    End If

End Sub

Private Sub ForeColorChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnForeRed) Then
        wfh.Foreground = New SolidColorBrush(Colors.Red)
    ElseIf sender.Equals(rdbtnForeYellow) Then
        wfh.Foreground = New SolidColorBrush(Colors.Yellow)
    ElseIf UIIsReady = True Then
        wfh.Foreground = initForeBrush
    End If

End Sub

Private Sub FontChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnTimes) Then
        wfh.FontFamily = New FontFamily("Times New Roman")
    ElseIf sender.Equals(rdbtnWingdings) Then
        wfh.FontFamily = New FontFamily("Wingdings")
    ElseIf UIIsReady = True Then
        wfh.FontFamily = initFontFamily
    End If

End Sub

Private Sub FontSizeChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnTen) Then
        wfh.FontSize = 10
    ElseIf sender.Equals(rdbtnTwelve) Then
        wfh.FontSize = 12
    ElseIf UIIsReady = True Then
        wfh.FontSize = initFontSize
    End If

End Sub

Private Sub StyleChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnItalic) Then
        wfh.FontStyle = FontStyles.Italic
    ElseIf UIIsReady = True Then
        wfh.FontStyle = initFontStyle
    End If

End Sub

Private Sub WeightChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnBold) Then
        wfh.FontWeight = FontWeights.Bold
    ElseIf UIIsReady = True Then
        wfh.FontWeight = initFontWeight
    End If

End Sub
private void BackColorChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnBackGreen)
        wfh.Background = new SolidColorBrush(Colors.LightGreen);
    else if (sender == rdbtnBackSalmon)
        wfh.Background = new SolidColorBrush(Colors.LightSalmon);
    else if (UIIsReady == true)
        wfh.Background = initBackBrush;
}

private void ForeColorChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnForeRed)
        wfh.Foreground = new SolidColorBrush(Colors.Red);
    else if (sender == rdbtnForeYellow)
        wfh.Foreground = new SolidColorBrush(Colors.Yellow);
    else if (UIIsReady == true)
        wfh.Foreground = initForeBrush;
}

private void FontChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnTimes)
        wfh.FontFamily = new FontFamily("Times New Roman");
    else if (sender == rdbtnWingdings)
        wfh.FontFamily = new FontFamily("Wingdings");
    else if (UIIsReady == true)
        wfh.FontFamily = initFontFamily;
}
private void FontSizeChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnTen)
        wfh.FontSize = 10;
    else if (sender == rdbtnTwelve)
        wfh.FontSize = 12;
    else if (UIIsReady == true)
        wfh.FontSize = initFontSize;
}
private void StyleChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnItalic)
        wfh.FontStyle = FontStyles.Italic;
    else if (UIIsReady == true)
        wfh.FontStyle = initFontStyle;
}
private void WeightChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnBold)
        wfh.FontWeight = FontWeights.Bold;
    else if (UIIsReady == true)
        wfh.FontWeight = initFontWeight;
}

Siehe auch

Aufgaben

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

Konzepte

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

Referenz

ElementHost

WindowsFormsHost

Weitere Ressourcen

WPF-Designer