演练:在 Windows 窗体中承载 Windows Presentation Foundation 控件

更新:2007 年 11 月

Windows Presentation Foundation (WPF) 提供用于创建应用程序的丰富环境。但是,如果您在 Windows 窗体代码上有大量投入,那么更有效的办法可能是用 WPF 来扩展现有的 Windows 窗体应用程序,而不是从头开始重新编写应用程序。常见的方案是将用 WPF 实现的一个或多个页面嵌入 Windows 窗体应用程序。

本演练引导您创建一个在 Windows 窗体应用程序中承载 WPF 页面的应用程序。该页面是打包在一个 DLL 中的简单数据输入应用程序。本示例设计为在外观和功能上与在 Windows Presentation Foundation 中承载 Windows 窗体复合控件的示例几乎完全相同。主要区别在于承载方案是相反的。

说明:

承载的页面从严格意义上而言不是一个 WPF 控件,而是一个打包在 DLL 中的普通 WPF 页面。但是,在窗体上承载 WPF 控件的技术与承载普通页面的技术完全相同。有关 WPF 控件的进一步讨论,请参见控件自定义

本演练分为两部分。第一部分简要介绍 WPF 页面的实现。第二部分详细讨论如何在 Windows 窗体应用程序中承载该页面、从该页面接收事件以及访问该页面的一些属性。

本演练涉及以下任务:

  • 实现 Windows Presentation Foundation 页面。

  • 实现 Windows 窗体宿主应用程序。

有关本演练中演示的任务的完整代码清单,请参见在 Windows 窗体中承载简单的 Windows Presentation Foundation 控件的示例

先决条件

您需要以下组件来完成本演练:

  • Visual Studio 2008.

实现 Windows Presentation Foundation 页面

本示例中使用的 WPF 页面是一个简单的数据输入窗体,它接受用户的姓名和地址。当用户单击两个按钮之一来指示任务已完成时,该页面引发一个自定义事件,将该信息返回到主机。该页面的形式和功能在本质上与演练:在 Windows Presentation Foundation 中承载 Windows 窗体复合控件中使用的 Windows 窗体控件完全相同。在自定义该页面以便承载于 Windows 窗体窗体上时,没有需要特别注意的事项。您可以轻松地将它加载到一个更大 WPF 页面上的 Frame。下图显示呈现的页面。

Windows Presentation Foundation 页面

简单的 WPF 控件

创建项目

若要开始创建项目,请执行以下操作:

  1. 启动 Microsoft Visual Studio,打开“新建项目”对话框。

  2. 选择“WPF 浏览器应用程序”模板。

  3. 将新项目命名为 MyControls,并将它置于一个便于命名的顶级文件夹中,如 WfHostingWpf。稍后会将宿主应用程序也放入该文件夹中。单击“确定”创建项目。默认项目包含一个名为 Page1 的页面。

  4. 在解决方案资源管理器中右击项目名称,然后选择“属性”。

  5. 将“输出类型”设置为“类库”,以便将该页面编译为一个 DLL。

  6. 从项目中删除应用程序定义文件 MyApp.xaml 和 MyApp.xaml.cs。只有当您要将该页面实现为一个应用程序时,才需要这些文件。

说明:

当您将 WPF 应用程序编译为一个类库时,将无法启动它来查看所呈现的页面。为此,您可能会发现在应用程序完全实现之前,将输出类型保留为“Windows 应用程序”是很方便的。这样,您就可以通过启动应用程序来检查页面的外观。对结果满意后,再删除应用程序定义文件,并将输出类型改为“类库”以便将它编译为 DLL。

您的项目应当具有对以下系统 DLL 的引用。如果其中有任何 DLL 默认情况下未包括在您的项目中,请将它添加到您的项目中。

  • System

  • PresentationCore

  • PresentationFramework

  • WindowsBase

实现页面的用户界面

WPF 页面的用户界面 (UI) 是用可扩展应用程序标记语言 (XAML) 实现的。它设计为在外观和功能上与演练:在 Windows Presentation Foundation 中承载 Windows 窗体复合控件中讨论的 Windows 窗体控件类似。该页面的输入数据 UI 包含 5 个 TextBox 元素。每个 TextBox 元素都有一个充当标签的关联 TextBlock 元素。页面底部有两个 Button 元素,它们是“确定”和“取消”。当用户单击其中任何一个按钮时,页面将引发一个自定义事件,将该信息返回到主机。

基本布局

多个不同的 UI 元素包含在一个 Grid 元素中。您可以使用 Grid 来排列页面中的内容,就像在 HTML 中使用 Table 元素一样。WPF 也有一个 Table 元素,但 Grid 更简易,且更适于简单的布局任务。

下面的示例演示了基本的布局代码。这些代码指定 Grid 元素中的列数和行数,从而定义页面的整体结构。用这些代码来替换 Page1.xaml 中的代码。

<Grid xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.Page1"
      Background="#DCDCDC"
      Width="375"
      Height="250"
      Name="rootElement"
      Loaded="Init">


...


<Grid.ColumnDefinitions>
  <ColumnDefinition Width="Auto" />
  <ColumnDefinition Width="Auto" />
  <ColumnDefinition Width="Auto"/>
  <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
  <RowDefinition Height="Auto" />
  <RowDefinition Height="Auto" />
  <RowDefinition Height="Auto" />
  <RowDefinition Height="Auto" />
  <RowDefinition Height="Auto" />
  <RowDefinition Height="Auto" />
</Grid.RowDefinitions>

向 Grid 中添加 TextBlock 和 TextBox 元素

在网格中放入一个 UI 元素,并将该元素的 RowPropertyColumnProperty 属性设置为适当的行号和列号。请记住行号和列号是从零开始的。通过设置元素的 ColumnSpanProperty 属性,可以使该元素跨多列。有关 Grid 元素的更多信息,请参见如何:创建网格元素

下面的示例演示页面的 TextBoxTextBlock 元素及其 RowPropertyColumnProperty 属性(设置这些属性是为了使元素在网格中正确定位)。将这些代码添加到 Page1.xaml 中 Grid 元素的紧下方。

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

设置 UI 元素的样式

数据输入窗体上的许多元素都有类似的外观,这意味着它们在几个属性的设置方面是完全相同的。本代码示例使用 Style 元素定义元素类的标准属性 (property) 设置,而不是分别设置每个元素的属性 (attribute)。此方法降低了页面的复杂度,并使您可以通过一个样式属性改变多个元素的外观。

Style 元素包含在 Grid 元素的 Resources 属性中,因此可供页面上的所有元素使用。如果对样式进行命名,则可通过添加一个设置为该样式的名称的 Style 元素来将该样式应用于元素。未命名的样式将成为元素的默认样式。有关 WPF 样式的更多信息,请参见样式设置和模板化

下面的示例演示 WPF 页面的 Style 元素。将这些代码添加到 Page1.xaml 中 Grid 元素的紧下方。要查看样式是如何应用于元素的,请参见上面的代码示例。例如,最后一个 TextBlock 元素具有 inlineText 样式,最后一个 TextBox 元素使用默认样式。

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

添加“OK”(确定)和“Cancel”(取消)按钮

页面上的最后两个元素是“OK”(确定)和“Cancel”(取消)Button 元素,它们占据 Grid 的最后两行的前两列。这些元素使用常用事件处理程序 ButtonClicked,以及在前面的代码示例中定义的默认 Button 样式。将下面的代码添加到 Page1.xaml 中最后一个 TextBox 元素的紧下方。页面的 XAML 部分现已完成。

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

实现页面的代码隐藏文件

WPF 页面的代码隐藏文件 Page1.xaml.cs 实现四个基本任务:

  1. Application 对象注册页面的 DLL 名称,使它知道从哪里加载该页面。

  2. 处理当用户单击某个按钮时发生的事件。

  3. TextBox 元素中检索数据,并将它们打包在一个自定义的事件参数对象中。

  4. 引发自定义的 OnButtonClick 事件,通知主机用户已完成并将数据传回主机。

该页面还公开许多颜色和字体属性,使您可以控制页面的外观。与用于承载 Windows 窗体控件的 WindowsFormsHost 类不同,ElementHost 类仅公开页面的 Background 属性。为了保持本代码示例与演练:在 Windows Presentation Foundation 中承载 Windows 窗体复合控件中讨论的示例的相似性,该页面直接公开其余的属性。

代码隐藏文件的基本结构

代码隐藏文件包含一个命名空间 MyControls,该命名空间包含两个类,即 Page1 和 MyControlEventArgs。将 Page1.xaml.cs 中的代码替换为以下代码。

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

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

第一个类 Page1 是一个分部类,它包含实现在 Page1.xaml 中定义的 UI 的功能的代码。当分析 Page1.xaml 时,XAML 转换为相同的分部类,两个分部类合并为编译后的页面。为此,代码隐藏文件中的类名必须与分配给 Page1.xaml 的类名匹配,并且它必须继承自页面的根元素。第二个类 MyControlEventArgs 是一个事件参数类,用于将数据发回主机。

初始化 Page1 类

下面的代码示例实现几个基本任务:

  • 声明一个私有事件 OnButtonClick 以及它的关联委托 MyControlEventHandler。

  • 创建几个存储用户数据的私有全局变量。这些数据是通过对应的属性公开的。

  • 为页面的 Loaded 事件实现一个处理程序 Init。此处理程序通过将 Page1.xaml 中定义的值赋给全局变量来初始化这些变量。为此,它使用指定给典型 TextBlock 元素 nameLabel 的 Name 来访问该元素的属性设置。

将下面的代码添加到 Page1 类中。

public partial class Page1 : Grid
{
    public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
    public event MyControlEventHandler OnButtonClick;
    private FontWeight _fontWeight;
    private double _fontSize;
    private FontFamily _fontFamily;
    private FontStyle _fontStyle;
    private SolidColorBrush _foreground;
    private SolidColorBrush _background;

    private void Init(object sender, EventArgs e)
    {
        //They all have the same style, so use nameLabel to set initial values.
        _fontWeight = nameLabel.FontWeight;
        _fontSize = nameLabel.FontSize;
        _fontFamily = nameLabel.FontFamily;
        _fontStyle = nameLabel.FontStyle;
        _foreground = (SolidColorBrush)nameLabel.Foreground;
        _background = (SolidColorBrush)rootElement.Background;
    }

处理按钮的 Click 事件

用户通过单击页面底部的“OK”(确定)按钮或“Cancel”(取消)按钮来表明数据输入任务已完成。两个按钮使用相同的 Click 事件处理程序 ButtonClicked。两个按钮均有一个名称,即 btnOK 或 btnFalse,这样处理程序就可以通过检查 sender 参数的值来确定单击的是哪个按钮。处理程序执行以下操作:

  • 创建一个包含页面的 TextBox 元素中的数据的 MyControlEventArgs 对象。

  • 如果用户单击“Cancel”(取消)按钮,将 MyControlEventArgs 对象的 IsOK 属性设置为 false。

  • 引发 OnButtonClick 事件,该事件通知主机用户已完成并传回所收集的数据。

将以下代码添加到 Page1 类中 Init 方法的下方。

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

创建属性

该类的其余部分仅仅公开与上面讨论的全局变量对应的属性。当属性更改时,set 访问器通过更改对应的元素属性并更新底层的全局变量来修改页面的外观。

将下面的代码添加到 Page1 类中。

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

将数据发回主机

文件中的最后一个组件是 MyControlEventArgs 类,它用于将所收集的数据发回主机。将下面的代码添加到 MyControls 命名空间。具体实现非常简单,不在这里进一步讨论。

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

实现 Windows 窗体宿主应用程序

Windows 窗体宿主应用程序使用 ElementHost 对象在窗体上承载 WPF 页面。该应用程序处理页面的 OnButtonClick 事件以接收来自窗体的数据。该应用程序还具有一组选项按钮,供您用来修改页面的外观。下面的屏幕快照显示所呈现的窗体。

承载于 Windows 窗体应用程序中的 Windows Presentation Foundation 页面

Windows 窗体承载 Avalon 控件

创建项目

若要开始创建项目,请执行以下操作:

  1. 启动 Visual Studio,打开“新建项目”对话框。

  2. 选择“C# 项目”和“Windows 窗体应用程序”模板。

  3. 将新项目命名为 WFHost,并将它置于 MyControls 项目所在的同一顶级文件夹中。单击“确定”创建项目。

您还需要添加一个对包含 WPF 页的 DLL 的引用:

  1. 在解决方案资源管理器中单击项目名称,然后选择“添加引用”。

  2. 单击“浏览”选项卡,定位到包含 MyControls.dll 的文件夹。

  3. 选择 MyControls.dll,然后单击“确定”将该 DLL 添加到引用列表中。

  4. 在解决方案资源管理器中,添加一个对名为 WindowsFormsIntegration.dll 的 WindowsFormsIntegration 程序集的引用。

实现窗体的用户界面设计

打开 Windows 窗体设计器,使窗体的布局如实现 Windows 窗体宿主应用程序中的图示所示:

  1. 扩展默认窗体以容纳控件和 WPF 页。

  2. 在窗体的右上角添加一个 System.Windows.Forms.Panel 控件以容纳 WPF 页。

  3. 添加六组 System.Windows.Forms.RadioButton 控件,如图所示。

  4. 在窗体的右下角添加五个 System.Windows.Forms.Label 控件,如图所示。这些控件充当 WPF 控件返回的数据的标签。

  5. 向在上一步中添加的每个 Label 控件的右侧添加一个 Label 控件。将每个控件的 Text 属性设置为“""”。这些控件显示 WPF 控件返回的数据。

  6. 添加另一个 Label 控件以充当上两步添加的控件组的标题。由于此 Label 旨在充当组的标题,因此使字号比组内的控件大两磅。

初始化窗体

通常在窗体的 Load 事件处理程序中实现承载代码。在 Windows 窗体设计器中,双击窗体创建一个 Load 事件处理程序方法。下面的代码示例包括示例的 Load 事件处理程序(WPF 页的 Loaded 事件的处理程序),以及后面使用的几个全局变量的声明。将 Form1.cs 中的代码替换为以下代码。

partial class Form1 : Form
{
    private ElementHost ctrlHost;
    private MyControls.Page1 wpfAddressCtrl;
    System.Windows.FontWeight initFontWeight;
    double initFontSize;
    System.Windows.FontStyle initFontStyle;
    System.Windows.Media.SolidColorBrush initBackBrush;
    System.Windows.Media.SolidColorBrush initForeBrush;
    FontFamily initFontFamily;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ctrlHost = new ElementHost();
        ctrlHost.Dock = DockStyle.Fill;
        panel1.Controls.Add(ctrlHost);
        wpfAddressCtrl = new MyControls.Page1();
        wpfAddressCtrl.InitializeComponent();
        ctrlHost.Child = wpfAddressCtrl;

        wpfAddressCtrl.OnButtonClick += 
            new MyControls.Page1.MyControlEventHandler(
            avAddressCtrl_OnButtonClick);
        wpfAddressCtrl.Loaded += new RoutedEventHandler(
            avAddressCtrl_Loaded);
    }

    void avAddressCtrl_Loaded(object sender, EventArgs e)
    {
        initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
        initForeBrush = wpfAddressCtrl.MyControl_Foreground;
        initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
        initFontSize = wpfAddressCtrl.MyControl_FontSize;
        initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
        initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
    }

前面的代码示例中的 Form1_Load 方法演示了承载 WPF 控件的常规过程:

  1. 创建一个新的 ElementHost 对象。

  2. 将控件的 Dock 属性设置为 DockStyle.Fill

  3. ElementHost 控件添加到 Panel 控件的 Controls 集合。

  4. 创建 WPF 页的一个实例。

  5. 在窗体中承载该页面,方法是:将该页面指定给 ElementHost 控件的 Child 属性。

Form1_Load 方法中的余下两行向两个页面事件附加处理程序:

  • OnButtonClick 是一个自定义事件,当用户单击“OK”(确定)或“Cancel”(取消)按钮时,页面将触发该事件。您处理该事件,以获取用户响应并收集用户填入的任何数据。

  • Loaded 是一个标准事件,当 WPF 页面已完全加载时将引发该事件。在这里使用该事件是因为示例需要使用页面中的属性初始化几个全局变量。在窗体的 Load 事件发生时,页面未完全加载,这些值仍设置为 null。您需要一直等到页面 Loaded 事件发生,然后才能访问这些属性。

Loaded 事件处理程序显示在前面的代码示例中。OnButtonClick 处理程序在下一节讨论。

处理 OnButtonClick

当用户单击“OK”(确定)或“Cancel”(取消)按钮时,会发生 OnButtonClick 事件。

事件处理程序检查事件参数的 IsOK 字段,确定单击的是哪个按钮。lbldata 变量与前面讨论的不可见 Label 控件对应。如果用户单击“OK”(确定)按钮,页面的 TextBox 控件中的数据将分配给对应的 Label 控件。如果用户单击“Cancel”(取消),Text 值将设置为 null。

将以下代码添加到 Form1.cs 中。现在可以编译并运行应用程序。

void avAddressCtrl_OnButtonClick(
    object sender, 
    MyControls.MyControlEventArgs args)
{
    if (args.IsOK)
    {
        lblAddress.Text = "Street Address: " + args.MyStreetAddress;
        lblCity.Text = "City: " + args.MyCity;
        lblName.Text = "Name: " + args.MyName;
        lblState.Text = "State: " + args.MyState;
        lblZip.Text = "Zip: " + args.MyZip;
    }
    else
    {
        lblAddress.Text = "Street Address: ";
        lblCity.Text = "City: ";
        lblName.Text = "Name: ";
        lblState.Text = "State: ";
        lblZip.Text = "Zip: ";
    }
}

修改 Windows Presentation Foundation 页面的外观

使用窗体左侧的 RadioButton 控件,用户可以更改 WPF 页面的前景和背景色以及几个字体属性。背景色由 ElementHost 对象公开。其余属性则作为页面的自定义属性公开。

双击窗体上的 RadioButton 控件可为对应的 CheckedChanged 事件处理程序创建模板。从以下处理程序中提取代码,将它们添加到 Form1.cs 中对应的处理程序。

private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = initBackBrush;
}

private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}

private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}

private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}

private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}

private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}

private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}

private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new FontFamily("WingDings");
}

private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = initFontSize;
}

private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 10;
}

private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 12;
}

private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}

private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}

private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}

private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}

请参见

任务

演练:在 Windows 窗体中承载 Windows Presentation Foundation 复合控件

概念

演练:在 Windows Presentation Foundation 中承载 Windows 窗体复合控件

参考

ElementHost

WindowsFormsHost

其他资源

WPF 设计器