在WinForms应用中嵌入WPF控件

WinForms应用程序在用户界面(UI)方面的能力相较于WPF有所限制。但这是否意味着必须将整个应用从WinForms迁移到WPF呢?答案是不一定的。有时候,可以通过使用WPF控件来轻松地为WinForms应用进行“整容”。

顺便说一句,如果想升级Windows Forms应用程序,应该考虑HTML5而不是WPF。虽然个人非常喜欢使用WPF,但是升级到HTML5可以让以更低的成本获得一个多平台的Web应用程序,特别是如果使用转换工具自动进行转换的话。已经完成了多个这样的项目,这肯定比重写为WPF要容易。

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

MSDN有一篇关于“在Windows Forms中托管WPF复合控件”的文章,但认为它太复杂了。在这里展示的是一个简单的例子,如何在Windows Forms应用程序中托管WPF控件,这种方式简单易学,并且从项目架构的角度来看也更加合适。

步骤

让从编写WPF控件开始。目标是一个简单的组合框控件,包含具有“客户”的“网格样式”属性:

<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代码所示,定义了一个以客户为项目源的组合框。组合框有一个项目模板,用于以“网格样式”展示客户详细信息:在WPF中,这可以通过使用三个标签并将它们的上下文绑定到“客户”类属性来轻松完成。

这一步实际上更简单。创建了一个简单的类,它继承自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控件作为子元素持有。请注意,已经覆盖了默认的Designer Smart-Tag和DesignerSerializer属性,以防止设计器覆盖Child元素。

首先,只需要将新控件拖放到Windows Forms中:

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; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485