65.9K
CodeProject 正在变化。 阅读更多。
Home

如何轻松地将 WPF 控件托管到 Windows Form 应用程序中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (29投票s)

2014 年 3 月 10 日

CPOL

3分钟阅读

viewsIcon

122909

downloadIcon

5117

本文演示了如何在 Windows Form 应用程序中轻松托管 WPF 控件。

引言

在本文中,我将演示如何创建一个“网格状”组合框,并将其托管在 Windows Form 应用程序中。

背景

与 WPF 相比,WinForms 应用程序的用户界面 (UI) 功能有限。这是否足以将整个应用程序从 WinForms 转换为 WPF?

我认为并非总是如此。有时,您可以使用 WPF 控件轻松地为您的应用程序“整容”。

顺便说一句,如果您想升级您的 Windows Form 应用程序,您应该考虑 HTML5 而不是 WPF。虽然我个人喜欢使用 WPF,但升级到 HTML5 将使您以较低的成本获得一个多平台 Web 应用程序,特别是如果您使用转置工具自动完成它。我做过很多这样的项目,而且肯定比重写成 WPF 更容易。

但是,与此同时,您可以使用“托管” - 将 WPF 控件嵌入到您的 Windows Form 应用程序中,以便利用 Windows Form 应用程序中 WPF 的丰富性(和容易性 - 在经过一些练习之后)。此外,在 WPF 中创建复杂的控件通常比在 Windows Form 中创建它们花费的时间更少。

MSDN 上有一篇文章关于“在 Windows Forms 中托管 WPF 复合控件”,但我认为它太复杂了。

我在这里展示的是一个简单的示例,说明如何以一种易于理解和实现的方式在 Windows Forms 应用程序中托管 WPF 控件,并且从项目架构的角度来看也更合适。

阶段

  1. 创建 WPF“网格状”组合框
  2. 创建 Windows Form 托管控件
  3. 将控件添加到 Windows Form 应用程序

1. 创建 WPF“网格状”组合框

让我们从编写 WPF 控件开始。

我们的目标是一个简单的组合框控件,其中包含“客户”的“网格状”属性

XAML

<UserControl x:Class="WindowsFormsControlLibrary1.ComboBoxWithGrid"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="250">
    <Grid>
        <ComboBox x:Name="comboBox"
        Margin="4"
        ItemsSource="{Binding Customers}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Label BorderThickness="1,1,0,1" 
                        BorderBrush="Black" Content="{Binding Path=Name}" />
                        <Label BorderThickness="1,1,0,1" 
                        BorderBrush="Black" Content="{Binding Path=Address}" />
                        <Label BorderThickness="1" 
                        BorderBrush="Black" Content="{Binding Path=TelephoneNumber}" />
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</UserControl>  

正如我们在上面的 XAML 中看到的,我们定义了一个以 customer 作为项目源的组合框。 组合框具有一个项目模板,用于以“网格状”样式呈现客户详细信息

在 WPF 中,使用三个标签并将其上下文绑定到“Customer”类属性很容易做到。

客户类

    public class Customer
    {
        public string Name { get; set; }
 
        public string Address { get; set; }
 
        public string TelephoneNumber { get; set; }
    } 

然后,我们剩下要做的就是编写 WPF 控件的代码

    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class ComboBoxWithGrid : UserControl
    {
        public ComboBoxWithGrid()
        {
            InitializeComponent();
            SelectedIndex = 0;
 
            this.DataContext = this;
        }
 
        public int SelectedIndex 
        {
            get
            {
               return comboBox.SelectedIndex;
            }
            set
            {
                comboBox.SelectedIndex = value;
            }
        } 
        public List<Customer> Customers { get; set; }
    } 

正如我们所看到的,代码非常简单,将 DataContext 设置为此,公开 Customers 列表以供外部和 XAML 数据绑定,并公开 select 索引仅供外部使用。

2. 创建 Windows Form 托管控件

这一步实际上更容易。 我正在创建一个简单的类,它继承自 System.Windows.Forms.Integration.ElementHost

    [Designer("System.Windows.Forms.Design.ControlDesigner, System.Design")]
    [DesignerSerializer("System.ComponentModel.Design.Serialization.TypeCodeDomSerializer , System.Design", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design")]
    public class ComboBoxWithGrid_WinformsHost : System.Windows.Forms.Integration.ElementHost
    {
        protected ComboBoxWithGrid m_WPFComboBoxWithGrid = new ComboBoxWithGrid();

        public ComboBoxWithGrid_WinformsHost()
        {
            base.Child = m_WPFComboBoxWithGrid;     
        }     

        public int SelectedIndex
        {
            get
            {
                return m_WPFComboBoxWithGrid.SelectedIndex;
            }
            set
            {
                m_WPFComboBoxWithGrid.SelectedIndex = value;
            }
        }
  
        public List<Customer> Customers
        {
            get
            {
                return m_WPFComboBoxWithGrid.Customers;
            }
            set
            {
                m_WPFComboBoxWithGrid.Customers = value;
            }
        }
    } 

此类继承自 ElementHost 对象,该对象将 WPF 控件作为子控件。

请注意,我已经覆盖回默认的设计器智能标记和 DesignerSerializer 属性,以防止设计器覆盖 Child 元素。

3. 将控件添加到 Windows Form 应用程序

首先,我们只需要将新控件拖放到我们的 Windows Form 中

然后,通过代码将客户列表连接到控件

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            var customers = new List<Customer>();
 
            for (int i = 0; i < 10; i++)
            {
                customers.Add(new Customer() { Name = "Name" + i, 
                Address = "Address" + i, TelephoneNumber = "TelephoneNumber" + i });
            }
 
            this.comboBoxWithGrid_WinformsHost1.Customers = customers;
 
            this.comboBoxWithGrid_WinformsHost1.SelectedIndex = 6;
        }
    }  
© . All rights reserved.