Exemplarische Vorgehensweise: Hosten eines zusammengesetzten WPF-Steuerelements in Windows Forms
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 ist das Einbetten eines oder mehrerer mit WPF implementierter Steuerelemente in die Windows Forms-Anwendung. Weitere Informationen zum Anpassen von WPF-Steuerelementen finden Sie unter Anpassung von Steuerelementen.
In dieser exemplarischen Vorgehensweise wird eine Anwendung vorgestellt, die ein zusammengesetztes WPF-Steuerelement hostet, um die Dateneingabe in einer Windows Forms-Anwendung auszuführen. Das zusammengesetzte Steuerelement ist in einer DLL gepackt. Diese allgemeine Prozedur kann auf komplexere Anwendungen und Steuerelemente erweitert werden. Diese exemplarische Vorgehensweise ist hinsichtlich Darstellung und Funktionalität nahezu identisch mit Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in WPF. Der Hauptunterschied liegt in einer Umkehrung des Hostingszenarios.
Die exemplarische Vorgehensweise ist in zwei Abschnitte unterteilt. Im ersten Abschnitt wird kurz die Implementierung des zusammengesetzten WPF-Steuerelements beschrieben. Im zweiten Abschnitt wird detailliert erläutert, wie das zusammengesetzte Steuerelement in einer Windows Forms-Anwendung gehostet wird, Ereignisse vom Steuerelement empfangen werden und 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, die in dieser exemplarischen Vorgehensweise veranschaulicht wurden, finden Sie unter Beispiel zum Hosten eines zusammengesetzten WPF-Steuerelements in Windows Forms.
Voraussetzungen
Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie die folgenden Komponenten:
- Visual Studio 2010.
Implementieren des zusammengesetzten WPF-Steuerelements
Das in diesem Beispiel verwendete zusammengesetzte WPF-Steuerelement ist ein einfaches Dateneingabeformular, in das der Name und die Adresse des Benutzers eingegeben werden. Wenn der Benutzer auf eine der zwei Schaltflächen klickt, um anzuzeigen, dass die Aufgabe beendet ist, löst das Steuerelement ein benutzerdefiniertes Ereignis aus, um diese Informationen an den Host zurückzugeben. Die folgende Abbildung zeigt das gerenderte Steuerelement.
Zusammengesetztes WPF-Steuerelement
Erstellen des Projekts
So starten Sie das Projekt
Starten Sie Microsoft Visual Studio, und öffnen Sie das Dialogfeld Neues Projekt.
Wählen Sie in Visual C# und der Windows-Kategorie die Vorlage WPF-Benutzersteuerelementbibliothek aus.
Geben Sie für das neue Projekt den Namen MyControls ein.
Geben Sie für den Speicherort einen passend benannten Ordner der obersten Ebene an, z. B. WindowsFormsHostingWpfControl. Später legen Sie die Hostanwendung in diesem Ordner ab.
Klicken Sie auf OK, um das Projekt zu erstellen. Das Standardprojekt enthält ein einzelnes Steuerelement mit dem Namen UserControl1.
Benennen Sie im Projektmappen-Explorer UserControl1 in MyControl1 um.
Das Projekt sollte Verweise auf die folgenden System-DLLs aufweisen. Wenn diese DLLs nicht standardmäßig enthalten sind, fügen Sie sie dem Projekt hinzu.
PresentationCore
PresentationFramework
System
WindowsBase
Erstellen der Benutzeroberfläche
Die user interface (UI) für das zusammengesetzte Steuerelement wird mit Extensible Application Markup Language (XAML) implementiert. Die UI des zusammengesetzten Steuerelements besteht aus fünf TextBox-Elementen. Jedes TextBox-Element verfügt über ein zugeordnetes TextBlock-Element, das als Bezeichnung dient. Zwei Button-Elemente befinden sich im unteren Bereich: OK und Abbrechen. Wenn der Benutzer auf eine der zwei Schaltflächen klickt, löst das Steuerelement ein benutzerdefiniertes Ereignis aus, um die Informationen an den Host zurückzugeben.
Grundlegendes Layout
Die verschiedenen UI-Elemente sind in einem Grid-Element enthalten. Sie können den Inhalt des zusammengesetzten Steuerelements anordnen, indem Sie das Grid-Element auf ähnliche Weise verwenden wie ein Table-Element in HTML. WPF verfügt auch über ein Table-Element, aber das Grid-Element ist einfacher und für einfache Layoutaufgaben besser geeignet.
Das folgende XAML-Beispiel zeigt das grundlegende Layout. Dieser XAML-Code definiert durch Angabe der Anzahl von Spalten und Zeilen im Grid-Element die Gesamtstruktur des Steuerelements.
Ersetzen Sie in "MyControl1.xaml" den vorhandenen XAML-Code durch den folgenden XAML-Code:
<Grid xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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 der Elemente TextBlock und TextBox zum Raster
Sie platzieren ein UI-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 zu Grid-Elementen finden Sie unter Gewusst wie: Erstellen eines Elements von Grid.
Der folgende XAML-Code zeigt die TextBox- und TextBlock-Elemente des zusammengesetzten Steuerelements mit den RowProperty- und ColumnProperty-Attributen, die so festgelegt sind, dass die Elemente korrekt im Raster platziert werden.
Fügen Sie in "MyControl1.xaml" den folgenden XAML-Code innerhalb des Grid-Elements 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 obigen XAML-Code mithilfe von Style-Elementen standardmäßige Eigenschafteneinstellungen für Elementklassen definiert. Dieser Ansatz reduziert die Komplexität des Steuerelements 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 im Steuerelement 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 zu WPF-Stilen finden Sie unter Erstellen von Formaten und Vorlagen.
Der folgende XAML-Code zeigt die Style-Elemente für das zusammengesetzte Steuerelement. Wie die Stile auf Elemente angewendet werden, sehen Sie im vorherigen XAML-Code. Das letzte TextBlock-Element z. B. hat den inlineText-Stil, 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 im zusammengesetzten Steuerelement 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 XAML-Code definiert wurde.
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 Code-Behind-Datei
Die CodeBehind-Datei "MyControl1.xaml.cs" implementiert drei wesentliche Aufgaben:
Behandlung des Ereignisses, das ausgelöst wird, wenn der Benutzer auf eine der Schaltflächen klickt.
Abrufen der Daten von den TextBox-Elementen und Packen der Daten in ein benutzerdefiniertes Ereignisargumentobjekt.
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.
Das Steuerelement macht auch eine Reihe von Farb- und Schriftarteigenschaften verfügbar, mit denen die Darstellung geändert werden kann. Im Gegensatz zur WindowsFormsHost-Klasse, die zum Hosten eines Windows Forms-Steuerelements verwendet wird, macht die ElementHost-Klasse nur die Background-Eigenschaft des Steuerelements verfügbar. Um die Ähnlichkeit zwischen diesem Codebeispiel und dem in Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in WPF erläuterten Beispiel beizubehalten, macht das Steuerelement die übrigen Eigenschaften direkt verfügbar.
Grundlegende Struktur der Code-Behind-Datei
Die CodeBehind-Datei besteht aus einem einzelnen Namespace MyControls, der die 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 mit dem Code, der die Funktionen der in "MyControl1.xaml" definierten UI implementiert. Wenn "MyControl1.xaml" analysiert wird, wird das XAML in die gleiche partielle Klasse umgewandelt, und die beiden partiellen Klassen werden zusammengeführt, um das kompilierte Steuerelement zu bilden. Daher muss der Klassenname in der CodeBehind-Datei mit dem "MyControl1.xaml" zugewiesenen Klassennamen übereinstimmen, und er muss vom Stammelement des Steuerelements erben. Die zweite Klasse, MyControlEventArgs, ist eine Ereignisklasse für Argumente, die verwendet wird, um die Daten an den Host zurückzusenden.
Öffnen Sie "MyControl1.xaml.cs". Ändern Sie die vorhandene Klassendeklaration, sodass sie den folgenden Namen aufweist und von Grid erbt.
public partial class MyControl1 : Grid
Initialisieren des Steuerelements
Im folgenden Code 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 Sie einen Handler Init für das Loaded-Ereignis des Steuerelements. Dieser Handler initialisiert die globalen Variablen, indem er ihnen die in "MyControl1.xaml" definierten Werte zuweist. Dazu verwendet er Name, der dem normalen TextBlock-Element nameLabel zugewiesen ist, um auf die Eigenschafteneinstellungen dieses Elements zuzugreifen.
Löschen Sie den vorhandenen Konstruktor, und fügen Sie der MyControl1-Klasse 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;
}
Behandeln der Klickereignisse der Schaltflächen
Der Benutzer zeigt durch Klicken auf die Schaltfläche OK oder Abbrechen an, dass er die Dateneingabe abgeschlossen hat. Beide Schaltflächen verwenden denselben Click-Ereignishandler, ButtonClicked. Beide Schaltflächen besitzen einen Namen, btnOK bzw. btnCancel, 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 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 den folgenden Code in der MyControl1-Klasse 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 oben erläuterten globalen Variablen entsprechen. Wenn sich eine Eigenschaft ändert, ändert der set-Accessor die Darstellung des Steuerelements, indem er die entsprechenden Elementeigenschaften ändert und die zugrunde liegenden globalen Variablen aktualisiert.
Fügen Sie der MyControl1-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; }
}
}
Erstellen Sie die Projektmappe. 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 behandelt das OnButtonClick-Ereignis, um die Daten vom zusammengesetzten Steuerelement zu empfangen. Die Anwendung verfügt auch über eine Reihe von Optionsfeldern, mit denen Sie die Darstellung des Steuerelements ändern können. Die folgende Abbildung zeigt die Anwendung.
Zusammengesetztes WPF-Steuerelement, das in einer Windows Forms-Anwendung gehostet wird
Erstellen des Projekts
So starten Sie das Projekt
Starten Sie Visual Studio, und öffnen Sie das Dialogfeld Neues Projekt.
Wählen Sie in Visual C# und der Windows-Kategorie die Vorlage Windows Forms-Anwendung aus.
Geben Sie für das neue Projekt den Namen WFHost ein.
Geben Sie für den Speicherort den Ordner der obersten Ebene an, der auch das Projekt "MyControls" enthält.
Klicken Sie auf OK, um das Projekt zu erstellen.
Außerdem müssen Sie Verweise auf die DLL hinzufügen, die MyControl1 und andere Assemblys enthält.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen, und klicken Sie dann auf Verweis hinzufügen.
Klicken Sie auf die Registerkarte Durchsuchen, und navigieren Sie zu dem Ordner, der "MyControls.dll" enthält. In dieser exemplarischen Vorgehensweise ist dies der Ordner "MyControls\bin\Debug".
Wählen Sie "MyControls.dll" aus, und klicken Sie dann auf OK.
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 mit dem zusammengesetzten WPF-Steuerelement interagieren.
Öffnen Sie Form1 im Windows Forms-Designer.
Vergrößern Sie das Formular, sodass ausreichend Platz für die Steuerelemente vorhanden ist.
Fügen Sie in der oberen rechten Ecke des Formulars ein System.Windows.Forms.Panel-Steuerelement für das zusammengesetzte WPF-Steuerelement hinzu.
Fügen Sie dem Formular die folgenden System.Windows.Forms.GroupBox-Steuerelemente hinzu.
Name
Text
groupBox1
Hintergrundfarbe
groupBox2
Vordergrundfarbe
groupBox3
Font Size
groupBox4
Schriftfamilie
groupBox5
Schriftschnitt
groupBox6
Schriftbreite
groupBox7
Daten vom Steuerelement
Fügen Sie den System.Windows.Forms.GroupBox-Steuerelementen die folgenden System.Windows.Forms.RadioButton-Steuerelemente hinzu.
GroupBox
Name
Text
groupBox1
radioBackgroundOriginal
Ursprünglich
groupBox1
radioBackgroundLightGreen
LightGreen
groupBox1
radioBackgroundLightSalmon
LightSalmon
groupBox2
radioForegroundOriginal
Ursprünglich
groupBox2
radioForegroundRed
Rot
groupBox2
radioForegroundYellow
Gelb
groupBox3
radioSizeOriginal
Ursprünglich
groupBox3
radioSizeTen
10
groupBox3
radioSizeTwelve
12
groupBox4
radioFamilyOriginal
Ursprünglich
groupBox4
radioFamilyTimes
Times New Roman
groupBox4
radioFamilyWingDings
WingDings
groupBox5
radioStyleOriginal
Normal
groupBox5
radioStyleItalic
Kursiv
groupBox6
radioWeightOriginal
Ursprünglich
groupBox6
radioWeightBold
Fett
Fügen Sie dem letzten System.Windows.Forms.GroupBox-Steuerelement die folgenden System.Windows.Forms.Label-Steuerelemente hinzu. Diese Steuerelemente zeigen die vom zusammengesetzten WPF-Steuerelement zurückgegebenen Daten an.
GroupBox
Name
Text
groupBox7
lblName
Name:
groupBox7
lblAddress
Straße:
groupBox7
lblCity
Ort:
groupBox7
lblState
Bundesland:
groupBox7
lblZip
Postleitzahl:
Initialisieren des Formulars
Hostcode wird üblicherweise im Load-Ereignishandler des Formulars implementiert. Der folgende Code zeigt den Load-Ereignishandler, einen Handler für das Loaded-Ereignis des zusammengesetzten WPF-Steuerelements 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;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Media;
namespace MyControls
{
public partial class MyControl1 : 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;
}
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);
}
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;
}
}
}
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; }
}
}
}
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 vorangehenden Code zeigt die allgemeine Prozedur zum Hosten eines WPF-Steuerelements:
Erstellen Sie ein neues ElementHost-Objekt.
Legen Sie die Dock-Eigenschaft des Steuerelements auf DockStyle.Fill fest.
Fügen Sie das ElementHost-Steuerelement der Controls-Auflistung des Panel-Steuerelements hinzu.
Erstellen Sie eine Instanz des WPF-Steuerelements.
Hosten Sie das zusammengesetzte Steuerelement im Formular, indem Sie es der Child-Eigenschaft des ElementHost-Steuerelements zuweisen.
Durch die übrigen zwei Zeilen in der Form1_Load-Methode werden Handler an zwei Steuerelementereignisse angefügt:
OnButtonClick ist ein benutzerdefiniertes Ereignis, das vom zusammengesetzten Steuerelement 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 einem WPF-Steuerelement ausgelöst wird, wenn es vollständig geladen wurde. Hier wird das Ereignis verwendet, da im Beispiel mehrere globale Variablen, die Eigenschaften des Steuerelements verwenden, initialisiert werden müssen. Zum Zeitpunkt des Load-Ereignisses des Formulars ist das Steuerelement nicht vollständig geladen, und diese Werte sind immer noch auf null festgelegt. Sie müssen bis zum Loaded-Ereignis des Steuerelements warten, bevor Sie auf diese Eigenschaften zugreifen können.
Der Loaded-Ereignishandler wird im vorangehenden Code 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 zuvor erläuterten Label-Steuerelementen. Wenn der Benutzer auf die Schaltfläche OK geklickt hat, werden die Daten der TextBox-Steuerelemente 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 folgen Ereignishandlercode für das Click-Ereignis 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 Text hinzu, und klicken Sie dann auf OK. Der Text wird in den Beschriftungen angezeigt. Bisher wurde kein Code zum Behandeln der Optionsfelder hinzugefügt.
Ändern der Darstellung des Steuerelements
Mit den RadioButton-Steuerelementen des Formulars kann der Benutzer die Vorder- und Hintergrundfarben des zusammengesetzten WPF-Steuerelements und einige Schriftarteigenschaften ändern. Die Hintergrundfarbe wird durch das ElementHost-Objekt verfügbar gemacht. Die übrigen 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 überprüfen.
Siehe auch
Aufgaben
Exemplarische Vorgehensweise: Hosten eines zusammengesetzten 3D-WPF-Steuerelements in Windows Forms
Referenz
Konzepte
Exemplarische Vorgehensweise: Hosten eines zusammengesetzten Windows Forms-Steuerelements in WPF