逐步解說:在 Windows Presentation Foundation 中裝載 Windows Form 複合控制項

更新:2007 年 11 月

Windows Presentation Foundation (WPF) 提供用來建立應用程式的豐富環境。然而,長期開發 Windows Form 程式碼時,更有效的方式是在 WPF 應用程式中重複使用至少一部分的程式碼,而不是從頭重新撰寫程式碼。最常見的情形是當您擁有現成自訂的 Windows Form 控制項時。在某些情況下,您甚至沒有這些控制項的原始程式碼存取權。WPF 會提供在 WPF 應用程式中裝載 (Host) 這類控制項的直接程序。例如,在裝載特製化的 System.Windows.Forms.DataGridView 控制項時,您可以使用 WPF 進行大部分的程式設計工作。

這個逐步解說會引導您完成在 WPF 頁面上裝載複合 Windows Form 控制項的應用程式。這個一般程序可以延伸至更複雜的應用程式和控制項。

逐步解說分成兩個部分。第一個部分簡短說明 Windows Form 控制項的實作。第二個部分則詳細討論如何在 WPF 應用程式中裝載控制項、從控制項接收事件,以及存取控制項的部分屬性。

逐步解說將說明的工作包括:

  • 實作 Windows Form 控制項。

  • 使用 Windows Presentation Foundation 實作主應用程式 (Host Application)。

如需這個逐步解說中所說明之工作的完整程式碼清單,請參閱在 Windows Presentation Foundation 中裝載 Windows Form 複合控制項範例

必要條件

您需要下列元件才能完成此逐步解說:

  • Visual Studio 2008

實作 Windows Form 控制項

此範例中使用的 Windows Form 控制項是簡單的資料輸入表單。此表單會取得使用者的名稱和地址,然後使用自訂事件,將該資訊傳回給主應用程式 (Host)。下圖顯示呈現的控制項。

Windows Forms 控制項

簡單的 Windows Form 控制項

建立專案

若要啟動此專案:

  1. 啟動 Microsoft Visual Studio,並開啟 [新增專案] 對話方塊。

  2. 選取具有 [Windows Form 控制項程式庫] 範本的 [C# 專案]。

  3. 將新專案命名為 MyControls,然後按一下 [確定] 建立專案。預設專案包含一個名為 UserControl1 的控制項。

  4. 將 UserControl1 的名稱變更為 MyControl1。

您的專案應該參考下列系統 DLL。如果預設未包含下列 DLL,請將它們加入至專案。

  • System

  • System.Data

  • System.Drawing

  • System.Windows.Forms

  • System.XML

將控制項加入到表單中

若要將控制項加入至表單:

  • 開啟 MyControl1 的設計工具。

在表單上放置六個 System.Windows.Forms.Label 控制項與其對應的 System.Windows.Forms.TextBox 控制項,其大小和排列方式跟上圖一樣。在此範例中,TextBox 控制項的名稱為:

  • txtName

  • txtAddress

  • txtCity

  • txtState

  • txtZip

加入兩個標示為 [確定] 和 [取消] 的 System.Windows.Forms.Button 控制項。在此範例中,按鈕名稱分別為 btnOK 和 btnCancel。

實作支援程式碼

開啟表單的程式碼檢視。控制項會藉由引發自訂 OnButtonClick 事件,將所收集的資料傳回至其主應用程式。此資料會包含在事件引數物件中。下列程式碼範例顯示 event 和 delegate 宣告。將這段程式碼加入至程式碼檔,就放在設計工具所產生的程式碼下方。

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;

MyControlEventArgs 類別包含要傳回給主應用程式的資訊。將下列類別加入至表單的命名空間。

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

當使用者按一下 [確定] 或 [取消] 按鈕時,Control.Click 事件處理常式會建立 MyControlEventArgs 物件,該物件含有資料並會引發 OnButtonClick 事件。這兩個處理常式之間的唯一差異在於事件引數的 IsOK 屬性。此屬性可讓主應用程式判斷按下的是哪一個按鈕。[確定] 按鈕的這個屬性設為 true,而 [取消] 按鈕的這個屬性設為 false。下列程式碼範例顯示這兩個按鈕處理常式。將此程式碼加入至您的類別,放在本節第一個程式碼範例所顯示的 event 和 delegate 宣告下方。

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

為組件提供強式名稱並建置組件

對於 WPF 應用程式所要參考的這個組件而言,它必須具有強式名稱 (Strong Name)。若要建立強式名稱,請使用 Sn.exe 建立金鑰檔,並將它加入至專案的 AssemblyInfo.cs 檔案。

  1. 開啟 Visual Studio 命令提示字元。若要這麼做,請按一下 [開始] 功能表,然後選取 [所有程式/Microsoft Visual Studio 2008/Visual Studio Tools/Visual Studio 2008 命令提示字元]。這樣會啟動具有自訂環境變數的主控台視窗。

  2. 在命令提示字元中,使用 "cd" 命令移至您的專案資料夾。

  3. 執行下列命令,以便產生名稱為 MyControls.snk 的金鑰檔。

    Sn.exe -k MyControls.snk
    
  4. 若要將金鑰檔包含於專案中,請在 [方案總管] 中以滑鼠右鍵按一下專案名稱,並開啟 [屬性] 對話方塊。選取 [簽署] 索引標籤,然後輸入金鑰檔的名稱。

  5. 建置組件。此組建會產生名稱為 MyControls.dll 的 DLL。

使用 Windows Presentation Foundation 實作主應用程式

WPF 主應用程式使用 WindowsFormsHost 控制項來裝載 MyControl1。此應用程式會處理 OnButtonClick 事件,以便接收來自控制項的資料。此外,它還具備選項按鈕集合,可讓您從 WPF 頁面變更控制項的某些屬性。下圖顯示的是完成的應用程式。

完整的應用程式,包含內嵌於 Windows Presentation Foundation 頁面的控制項

內嵌於 WPF 頁面中的控制項

建立專案

若要啟動專案:

  1. 開啟 Visual Studio,然後選取 [新增專案]。

  2. 選取 [WPF 瀏覽器應用程式] 範本。

  3. 將專案命名為 WpfHost,然後按一下 [確定] 以開啟專案。

您也需要加入內含 MyControl1 之 DLL 的參考。以下是加入參考的最簡單方法。

  1. 在 [方案總管] 中,以滑鼠右鍵按一下專案名稱,然後啟動 [加入參考] 對話方塊。

  2. 按一下 [瀏覽] 索引標籤,然後瀏覽至 Windows Form 控制項的輸出資料夾。在此範例中,這個資料夾為 MyControls\bin\Debug。

  3. 選取含有該控制項的 DLL,然後按一下 [確定] 將它加入至參考清單中。對於在 Windows Presentation Foundation 中裝載 Windows Form 複合控制項範例而言,此 DLL 的名稱為 MyControls.dll。

  4. 在 [方案總管] 中,加入名為 WindowsFormsIntegration.dll 之 WindowsFormsIntegration 組件的參考。

實作基本配置

主應用程式的使用者介面 (UI) 會在 Page1.xaml 中實作。此檔案包含可定義頁面配置的可延伸標記語言 (XAML) 標記,並且會裝載 Windows Form 控制項。此頁面分為三個區域:

  • [控制項屬性] 面板,其中包含選項按鈕集合,可供您修改所裝載控制項的各種屬性。

  • [資料來源控制項] 面板,其中包含數個 TextBlock 項目,可顯示從所裝載控制項傳回的資料。

  • 裝載的控制項本身。

基本配置程式碼會顯示於下列程式碼範例中。這個範例省略了裝載 MyControl1 所需的標記程式碼,但我們稍後會進行討論。請用下列程式碼取代 Page1.xaml 中的程式碼。

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

第一個 StackPanel 項目包含好幾組 RadioButton 控制項,這些控制項可讓您修改所裝載控制項的各種預設屬性。後面接著是 WindowsFormsHost 項目,該項目會裝載 MyControl1。而最後一個 StackPanel 項目包含數個 TextBlock 項目,可顯示從所裝載控制項傳回的資料。項目的順序以及 DockHeight 屬性設定會絲毫不差地將裝載的控制項內嵌到頁面中。

裝載控制項

下列為前一個程式碼範例的編輯後版本,著重於裝載 MyControl1 所需的項目。

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

xmlns 命名空間對應屬性會建立含有所裝載控制項之 MyControls 命名空間的參考。此對應可讓您以 XAML 將 MyControl1 表示為 <mcl:MyControl1>。

程式碼範例中的兩個項目會處理裝載:

  • WindowsFormsHost 表示 WindowsFormsHost 項目,該項目可讓您在 WPF 頁面上裝載 Windows Form 控制項。

  • mcl:MyControl1 表示 MyControl1,它會加入至 WindowsFormsHost 項目的子系集合中。因此,此 Windows Form 控制項會呈現為 WPF 頁面的一部分,而您可以從此頁面與該控制項通訊。

實作程式碼後置檔案

程式碼後置 (Code-Behind) 的檔案 Page1.xaml.cs 包含程序性程式碼,可以實作上一節所討論之 UI 的功能。主要工作如下:

  • 將事件處理常式附加至 MyControl1 的 OnButtonClick 事件。

  • 根據選項按鈕集合的設定方式,修改 MyControl1 的各種屬性。

  • 顯示控制項所收集的資料。

初始化應用程式

初始化程式碼會包含在頁面之 Loaded 事件的事件處理常式中,而且會將事件處理常式附加至控制項的 OnButtonClick 事件。將下列程式碼複製到 Page1.xaml.cs 的 Page1 類別中。

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

因為先前討論的 XAML 程式碼會將 MyControl1 加入至 WindowsFormsHost 項目的子項目集合中,所以您可將 WindowsFormsHost 項目的 Child 轉型,以取得 MyControl1 的參考。然後,您可以使用該參考將事件處理常式附加至 OnButtonClick。

此了提供控制項本身的參考以外,WindowsFormsHost 還公開您可以從此頁面操作之控制項的數個屬性。初始化程式碼會將這些值指定給私用 (Private) 全域變數,以便稍後用在應用程式中。

處理 OnButtonClick 事件

當使用者按一下其中一個控制項按鈕時,MyControl1 會引發 OnButtonClick 事件。請將下列程式碼加入至 Page1 類別。

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

文字方塊中的資料會封裝在 MyControlEventArgs 物件中。如果使用者按一下 [確定] 按鈕,事件處理常式便會擷取資料並將資料顯示在 MyControl1 下面的面板中。

修改控制項的屬性

WindowsFormsHost 項目會公開所裝載控制項的數個預設屬性。因此,您可以變更控制項的外觀,使其更接近您的頁面樣式。左面板中的選項按鈕集,可供使用者修改數個色彩和字型屬性。每組按鈕都有 Click 事件的處理常式,該處理常式會偵測使用者的選項按鈕選取項目,並且變更控制項的對應屬性。將下列程式碼複製到 Page1 類別中。您現在可以編譯並執行應用程式了。

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

請參閱

工作

逐步解說:在 Windows Presentation Foundation 中裝載 Windows Form 控制項

概念

逐步解說:在 Windows Form 中裝載 Windows Presentation Foundation 控制項

參考

ElementHost

WindowsFormsHost

其他資源

WPF 設計工具