Wie kann ich ein WPF-Steuerelement in meine bestehende Windows Forms-Anwendung einbinden?

Voraussetzungen:

Plattform
.NET Framework 3.5 SP1
Sprachen
XAML, C#
Werkzeuge
Visual C# 2008
Zu bearbeitende Projekte
WPFApp

Einleitung:

In diesem Tutorial wird beschrieben, wie das WPF-Steuerelement BizCardFlow in eine bestehende Windows Forms-Anwendung integriert werden kann. Dabei wird ein Windows Forms-Steuerelement (ElementHost) zwischen Windows Forms-Anwendung und WPF-Steuerelement geschaltet, um die Interoperabilität von WPF zu gewährleisten.

Einbinden von BizCardFlow in eine bestehende Windows Forms-Anwendung

Das Einbinden des Steuerelements erfordert die Existenz einer bestehenden Anwendung. Um dies exemplarisch darzustellen wird in diesem Tutorial eine mit Visual Studio neu erstellte Windows Forms-Anwendung verwendet.

Hinzufügen der Verweise

Die Verweise können im Solution Explorer („Projektmappen-Explorer“ in der deutschen Version von Visual Studio) über einen Rechts-Klick auf das Verzeichnis „References“ („Verweise“) und den Kontext-Menü-Eintrag „Add Reference“ („Verweis hinzufügen“) hinzugefügt werden.

Aus der Kategorie .NET werden Verweise auf die folgenden Assemblies (Baugruppen) benötigt:

  • PresentationCore
  • PresentationFramework
  • WindowsBase

Hinzufügen des Steuerelements

Damit das WPF-Steuerelement in der Toolbox erscheint muss der aktuellen Solution (Projektmappe) das Steuerelemente-Projekt hinzugefügt werden.

Nun benötigt das Windows Forms-Projekt noch einen Verweis auf das WPF-Steuerelement-Projekt.

Danach kann das Formular, dem das Steuerelement hinzugefügt werden soll, geöffnet werden. In der Toolbox ist nun BizCardFlow zu sehen.

Dieser kann per Drag & Drop auf das Formular gelegt werden.

Visual Studio fügt tatsächlich jedoch ein ElementHost-Steuerelement hinzu, das auf BizCardFlow verweist.

BizCardFlow wird nun nach dem Kompilieren an den definierten Koordinaten angezeigt.

Binden von Daten

Das Steuerelement visualisiert Daten – ohne Daten keine Visualisierung. Um jetzt Daten an das Steuerelement zu binden, kann eine ObservableCollection mit Person-Objekten gefüllt werden.

Die ObservableCollection entspringt dem Namensraum System.Collections.ObjectModel aus der Assembly WindowsBase.dll. Person dem Namensraum Microsoft.WPF.Samples und liegt in der Assembly des WPF-Steuerelements Microsoft.WPF.Samples.BizCardFlow.dll – dem hinzugefügten Projekt.

    using System;
    using System.Collections.ObjectModel;
    using System.Windows.Forms;
    using Microsoft.WPF.Samples;

    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    var ppl =
    new ObservableCollection<Person>
    {
    new Person
    {
    Gender = "male",
    FirstName = "John",
    LastName = "Doe",
    //...
    },
    new Person
    {
    Gender = "male",
    FirstName = "John",
    LastName = "Doe",
    //...
    },
    //...
    };

    bizCardFlow1.ItemsSource = ppl;
    }
    }
    }

BizCardFlow visualisiert nun nach dem Kompilieren die zugewiesenen Daten. Wenn von außen, von der MFC-Anwendung, das Selektieren eines Datensatzes gewünscht ist, kann dies über die Eigenschaft SelectedIndex forciert werden.

Binden an die SelectedItem-Eigenschaft des Steuerelementes

WPF bringt eine völlig eigene Bindungs-Logik mit sich, die im Interoperabilitäts-Szenario leider nicht verwendet werden kann. Damit auf das jeweils aktuelle Element des BizCardFlow verwiesen werden kann (z.B. um die Daten in anderen Steuerelementen anzuzeigen) wirft BizCardFlow beim Wechsel des aktuellen Elements das Ereignis SelectedItemChanged. Auf dieses kann eine EventHandler-Methode registriert werden, die die Daten verarbeitet.

    using System;
    using System.Windows.Forms;
    using Microsoft.WPF.Samples;

    namespace WINApp
    {
    public partial class Form1
    : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    var data = new People().GetPersons();
    bizCardFlow1.SelectedItemChanged +=
    CoverFlowListSelectedItemChanged;
    bizCardFlow1.ItemsSource = data;

    }

    void CoverFlowListSelectedItemChanged(object sender, EventArgs e)
    {
    var person = bizCardFlow1.SelectedItem as Person;
    if(person == null) return;
    // Add data to textboxes...
    LastName.Text = person.LastName;
    FirstName.Text = person.FirstName;
    Email.Text = person.Email;
    Phone.Text = person.Phone;
    Address.Text = person.Address;
    Zipcode.Text = person.PostalCode;
    City.Text = person.City;
    }
    }
    }

WPF Fast Start