演练:使用 WindowsFormsHost 元素映射属性
更新:2007 年 11 月
本演练显示如何使用 PropertyMap 属性将 WPF 属性映射至承载的 Windows 窗体控件上的相应属性。
本演练涉及以下任务:
创建项目。
定义应用程序布局。
定义新的属性映射。
移除默认属性映射。
替换默认属性映射。
扩展默认属性映射。
有关本演练中演示的任务的完整代码清单,请参见使用 WindowsFormsHost 元素映射属性的示例。
完成后,您将能够将 WPF 属性映射至承载的 Windows 窗体控件上的相应属性。
注意 显示的对话框和菜单命令可能与“帮助”中所述的有所不同,具体取决于当前的设置或版本。若要更改设置,请在“工具”菜单上选择“导入和导出设置”。有关更多信息,请参见 Visual Studio 设置。
先决条件
您需要以下组件来完成本演练:
- Visual Studio 2008.
创建项目
创建和设置项目
创建名为 PropertyMappingWithWfh 的 WPF 应用程序项目。
在解决方案资源管理器中,添加一个对名为 WindowsFormsIntegration.dll 的 WindowsFormsIntegration 程序集的引用。
在解决方案资源管理器中,添加对 System.Drawing 和 System.Windows.Forms 程序集的引用。
定义应用程序布局
基于 WPF 的应用程序使用 WindowsFormsHost 元素来承载 Windows 窗体控件。
定义应用程序布局
在 WPF 设计器中打开 Window1.xaml。
用下面的代码替换现有代码。
<Window x:Class="Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="PropertyMappingWithWfh" Height="300" Width="300" Loaded="WindowLoaded"> <DockPanel Name="panel1" LastChildFill="True"> <WindowsFormsHost Name="wfHost" DockPanel.Dock="Left" SizeChanged="Window1_SizeChanged" FontSize="20" /> </DockPanel> </Window>
<Window x:Class="PropertyMappingWithWfh.Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="PropertyMappingWithWfh" Height="300" Width="300" Loaded="WindowLoaded"> <DockPanel Name="panel1" LastChildFill="True"> <WindowsFormsHost Name="wfHost" DockPanel.Dock="Left" SizeChanged="Window1_SizeChanged" FontSize="20" /> </DockPanel> </Window>
在代码编辑器中打开 Window1.xaml.cs。
在文件顶部导入以下命名空间。
Imports System.Drawing Imports System.Drawing.Drawing2D Imports System.Windows.Forms Imports System.Windows.Forms.Integration
using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Windows.Forms.Integration;
定义新的属性映射
WindowsFormsHost 元素提供若干默认属性映射。您可以通过对 WindowsFormsHost 元素的 PropertyMap 调用 Add 方法来添加新的属性映射。
定义新的属性映射
将下面的代码复制到 Window1 类的定义中。
' The AddClipMapping method adds a custom mapping ' for the Clip property. Private Sub AddClipMapping() wfHost.PropertyMap.Add( _ "Clip", _ New PropertyTranslator(AddressOf OnClipChange)) End Sub ' The OnClipChange method assigns an elliptical clipping ' region to the hosted control's Region property. Private Sub OnClipChange( _ ByVal h As Object, _ ByVal propertyName As String, _ ByVal value As Object) Dim host As WindowsFormsHost = h Dim cb As System.Windows.Forms.CheckBox = host.Child If cb IsNot Nothing Then cb.Region = Me.CreateClipRegion() End If End Sub ' The Window1_SizeChanged method handles the window's ' SizeChanged event. It calls the OnClipChange method explicitly ' to assign a new clipping region to the hosted control. Private Sub Window1_SizeChanged( _ ByVal sender As Object, _ ByVal e As SizeChangedEventArgs) Me.OnClipChange(wfHost, "Clip", Nothing) End Sub ' The CreateClipRegion method creates a Region from an ' elliptical GraphicsPath. Private Function CreateClipRegion() As [Region] Dim path As New GraphicsPath() path.StartFigure() path.AddEllipse(New System.Drawing.Rectangle( _ 0, _ 0, _ wfHost.ActualWidth, _ wfHost.ActualHeight)) path.CloseFigure() Return New [Region](path) End Function
// The AddClipMapping method adds a custom // mapping for the Clip property. private void AddClipMapping() { wfHost.PropertyMap.Add( "Clip", new PropertyTranslator(OnClipChange)); } // The OnClipChange method assigns an elliptical clipping // region to the hosted control's Region property. private void OnClipChange(object h, String propertyName, object value) { WindowsFormsHost host = h as WindowsFormsHost; System.Windows.Forms.CheckBox cb = host.Child as System.Windows.Forms.CheckBox; if (cb != null) { cb.Region = this.CreateClipRegion(); } } // The Window1_SizeChanged method handles the window's // SizeChanged event. It calls the OnClipChange method explicitly // to assign a new clipping region to the hosted control. private void Window1_SizeChanged(object sender, SizeChangedEventArgs e) { this.OnClipChange(wfHost, "Clip", null); } // The CreateClipRegion method creates a Region from an // elliptical GraphicsPath. private Region CreateClipRegion() { GraphicsPath path = new GraphicsPath(); path.StartFigure(); path.AddEllipse(new System.Drawing.Rectangle( 0, 0, (int)wfHost.ActualWidth, (int)wfHost.ActualHeight ) ); path.CloseFigure(); return( new Region(path) ); }
AddClipMapping 方法为 Clip 属性添加新的映射。
OnClipChange 方法会将 Clip 属性转换为 Windows 窗体Region 属性。
Window1_SizeChanged 方法用于处理窗口的 SizeChanged 事件,并调整剪辑区域的大小以适合应用程序窗口。
移除默认属性映射
通过对 WindowsFormsHost 元素的 PropertyMap 调用 Remove 方法来移除默认属性映射。
移除默认属性映射
将下面的代码复制到 Window1 类的定义中。
' The RemoveCursorMapping method deletes the default ' mapping for the Cursor property. Private Sub RemoveCursorMapping() wfHost.PropertyMap.Remove("Cursor") End Sub
// The RemoveCursorMapping method deletes the default // mapping for the Cursor property. private void RemoveCursorMapping() { wfHost.PropertyMap.Remove("Cursor"); }
RemoveCursorMapping 方法会删除 Cursor 属性的默认映射。
替换默认属性映射
通过移除默认映射并对 WindowsFormsHost 元素的 PropertyMap 调用 Add 方法,可以替换默认属性映射。
替换默认属性映射
将下面的代码复制到 Window1 类的定义中。
' The ReplaceFlowDirectionMapping method replaces the ' default mapping for the FlowDirection property. Private Sub ReplaceFlowDirectionMapping() wfHost.PropertyMap.Remove("FlowDirection") wfHost.PropertyMap.Add( _ "FlowDirection", _ New PropertyTranslator(AddressOf OnFlowDirectionChange)) End Sub ' The OnFlowDirectionChange method translates a ' Windows Presentation Foundation FlowDirection value ' to a Windows Forms RightToLeft value and assigns ' the result to the hosted control's RightToLeft property. Private Sub OnFlowDirectionChange( _ ByVal h As Object, _ ByVal propertyName As String, _ ByVal value As Object) Dim host As WindowsFormsHost = h Dim fd As System.Windows.FlowDirection = _ CType(value, System.Windows.FlowDirection) Dim cb As System.Windows.Forms.CheckBox = host.Child cb.RightToLeft = IIf(fd = System.Windows.FlowDirection.RightToLeft, _ RightToLeft.Yes, _ RightToLeft.No) End Sub ' The cb_CheckedChanged method handles the hosted control's ' CheckedChanged event. If the Checked property is true, ' the flow direction is set to RightToLeft, otherwise it is ' set to LeftToRight. Private Sub cb_CheckedChanged( _ ByVal sender As Object, _ ByVal e As EventArgs) Dim cb As System.Windows.Forms.CheckBox = sender wfHost.FlowDirection = IIf(cb.CheckState = CheckState.Checked, _ System.Windows.FlowDirection.RightToLeft, _ System.Windows.FlowDirection.LeftToRight) End Sub
// The ReplaceFlowDirectionMapping method replaces the // default mapping for the FlowDirection property. private void ReplaceFlowDirectionMapping() { wfHost.PropertyMap.Remove("FlowDirection"); wfHost.PropertyMap.Add( "FlowDirection", new PropertyTranslator(OnFlowDirectionChange)); } // The OnFlowDirectionChange method translates a // Windows Presentation Foundation FlowDirection value // to a Windows Forms RightToLeft value and assigns // the result to the hosted control's RightToLeft property. private void OnFlowDirectionChange(object h, String propertyName, object value) { WindowsFormsHost host = h as WindowsFormsHost; System.Windows.FlowDirection fd = (System.Windows.FlowDirection)value; System.Windows.Forms.CheckBox cb = host.Child as System.Windows.Forms.CheckBox; cb.RightToLeft = (fd == System.Windows.FlowDirection.RightToLeft ) ? RightToLeft.Yes : RightToLeft.No; } // The cb_CheckedChanged method handles the hosted control's // CheckedChanged event. If the Checked property is true, // the flow direction is set to RightToLeft, otherwise it is // set to LeftToRight. private void cb_CheckedChanged(object sender, EventArgs e) { System.Windows.Forms.CheckBox cb = sender as System.Windows.Forms.CheckBox; wfHost.FlowDirection = ( cb.CheckState == CheckState.Checked ) ? System.Windows.FlowDirection.RightToLeft : System.Windows.FlowDirection.LeftToRight; }
ReplaceFlowDirectionMapping 方法会替换 FlowDirection 属性的默认映射。
OnFlowDirectionChange 方法会将 FlowDirection 属性转换为 Windows 窗体RightToLeft 属性。
cb_CheckedChanged 方法用于处理 CheckBox 控件上的 CheckedChanged 事件。它会基于 CheckState 属性的值对 FlowDirection 属性赋值。
扩展默认属性映射
您可以使用默认属性映射,也可以利用自己的映射对其进行扩展。
扩展默认属性映射
将下面的代码复制到 Window1 类的定义中。
' The ExtendBackgroundMapping method adds a property ' translator if a mapping already exists. Private Sub ExtendBackgroundMapping() If wfHost.PropertyMap("Background") IsNot Nothing Then wfHost.PropertyMap("Background") = PropertyTranslator.Combine( _ wfHost.PropertyMap("Background"), _ PropertyTranslator.CreateDelegate( _ GetType(PropertyTranslator), _ Me, _ "OnBackgroundChange")) End If End Sub ' The OnBackgroundChange method assigns a specific image ' to the hosted control's BackgroundImage property. Private Sub OnBackgroundChange(ByVal h As Object, ByVal propertyName As String, ByVal value As Object) Dim host As WindowsFormsHost = h Dim cb As System.Windows.Forms.CheckBox = host.Child Dim b As ImageBrush = value If Not (b Is Nothing) Then cb.BackgroundImage = New System.Drawing.Bitmap("C:\WINDOWS\Santa Fe Stucco.bmp") End If End Sub
// The ExtendBackgroundMapping method adds a property // translator if a mapping already exists. private void ExtendBackgroundMapping() { if (wfHost.PropertyMap["Background"] != null) { wfHost.PropertyMap["Background"] += new PropertyTranslator(OnBackgroundChange); } } // The OnBackgroundChange method assigns a specific image // to the hosted control's BackgroundImage property. private void OnBackgroundChange(object h, String propertyName, object value) { WindowsFormsHost host = h as WindowsFormsHost; System.Windows.Forms.CheckBox cb = host.Child as System.Windows.Forms.CheckBox; ImageBrush b = value as ImageBrush; if (b != null) { cb.BackgroundImage = new System.Drawing.Bitmap(@"C:\WINDOWS\Santa Fe Stucco.bmp"); } }
ExtendBackgroundMapping 方法会将自定义属性转换器添加到现有 Background 属性映射。
OnBackgroundChange 方法会将特定图像分配给承载的控件的 BackgroundImage 属性。在应用默认属性映射后,会调用 OnBackgroundChange 方法。
初始化属性映射
通过在 Loaded 事件处理程序中调用前面所述的方法,可以设置属性映射。
初始化属性映射
将下面的代码复制到 Window1 类的定义中。
' The WindowLoaded method handles the Loaded event. ' It enables Windows Forms visual styles, creates ' a Windows Forms checkbox control, and assigns the ' control as the child of the WindowsFormsHost element. ' This method also modifies property mappings on the ' WindowsFormsHost element. Private Sub WindowLoaded( _ ByVal sender As Object, _ ByVal e As RoutedEventArgs) System.Windows.Forms.Application.EnableVisualStyles() ' Create a Windows Forms checkbox control and assign ' it as the WindowsFormsHost element's child. Dim cb As New System.Windows.Forms.CheckBox() cb.Text = "Windows Forms checkbox" cb.Dock = DockStyle.Fill cb.TextAlign = ContentAlignment.MiddleCenter AddHandler cb.CheckedChanged, AddressOf cb_CheckedChanged wfHost.Child = cb ' Replace the default mapping for the FlowDirection property. Me.ReplaceFlowDirectionMapping() ' Remove the mapping for the Cursor property. Me.RemoveCursorMapping() ' Add the mapping for the Clip property. Me.AddClipMapping() ' Add another mapping for the Background property. Me.ExtendBackgroundMapping() ' Cause the OnFlowDirectionChange delegate to be called. wfHost.FlowDirection = System.Windows.FlowDirection.LeftToRight ' Cause the OnClipChange delegate to be called. wfHost.Clip = New RectangleGeometry() ' Cause the OnBackgroundChange delegate to be called. wfHost.Background = New ImageBrush() End Sub
// The WindowLoaded method handles the Loaded event. // It enables Windows Forms visual styles, creates // a Windows Forms checkbox control, and assigns the // control as the child of the WindowsFormsHost element. // This method also modifies property mappings on the // WindowsFormsHost element. private void WindowLoaded(object sender, RoutedEventArgs e) { System.Windows.Forms.Application.EnableVisualStyles(); // Create a Windows Forms checkbox control and assign // it as the WindowsFormsHost element's child. System.Windows.Forms.CheckBox cb = new System.Windows.Forms.CheckBox(); cb.Text = "Windows Forms checkbox"; cb.Dock = DockStyle.Fill; cb.TextAlign = ContentAlignment.MiddleCenter; cb.CheckedChanged += new EventHandler(cb_CheckedChanged); wfHost.Child = cb; // Replace the default mapping for the FlowDirection property. this.ReplaceFlowDirectionMapping(); // Remove the mapping for the Cursor property. this.RemoveCursorMapping(); // Add the mapping for the Clip property. this.AddClipMapping(); // Add another mapping for the Background property. this.ExtendBackgroundMapping(); // Cause the OnFlowDirectionChange delegate to be called. wfHost.FlowDirection = System.Windows.FlowDirection.LeftToRight; // Cause the OnClipChange delegate to be called. wfHost.Clip = new RectangleGeometry(); // Cause the OnBackgroundChange delegate to be called. wfHost.Background = new ImageBrush(); }
WindowLoaded 方法会处理 Loaded 事件并执行以下初始化。
创建 Windows 窗体CheckBox 控件。
调用在本演练前面部分定义的方法,来设置属性映射。
将初始值赋值给已映射的属性
按 F5 生成并运行该应用程序。单击复选框以查看 FlowDirection 映射的效果。单击复选框时,布局会反转其左右方向。
请参见
任务
演练:在 Windows Presentation Foundation 中承载 Windows 窗体控件