逐步解說:使用 WindowsFormsHost 項目對應屬性
本逐步解說顯示如何使用 PropertyMap 屬性將 WPF 屬性對應至裝載之 Windows Forms 控制項上的對應屬性。
逐步解說將說明的工作包括:
建立專案。
定義應用程式配置。
定義新的屬性對應。
移除預設的屬性對應。
取代預設的屬性對應。
擴充預設的屬性對應。
如需這個逐步解說中所說明之工作的完整程式碼清單,請參閱使用 WindowsFormsHost 項目對應屬性範例 (英文)。
完成時,就可以將 WPF 屬性對應至裝載之 Windows Forms 控制項上的對應屬性。
必要條件
您需要下列元件才能完成此逐步解說:
- Visual Studio 2008。
建立專案
若要建立並設定此專案
建立名為 PropertyMappingWithWfh 的 WPF 應用程式專案。
在 [方案總管] 中,加入名為 WindowsFormsIntegration.dll 的 WindowsFormsIntegration 組件之參考。
在 [方案總管] 中,加入 System.Drawing 和 System.Windows.Forms 組件的參考。
定義應用程式配置
WPF 架構應用程式會使用 WindowsFormsHost 項目裝載 Windows Forms 控制項。
若要定義應用程式配置
在 WPF 設計工具中開啟 Window1.xaml。
將現有的程式碼更換成下列程式碼。
<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>
<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>
在 [程式碼編輯器] 中開啟 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 Forms 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 Forms 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 Forms CheckBox 控制項。
呼叫您稍早在這個逐步解說中定義的方法,以設定屬性對應。
將初始值指派給對應的屬性。
按 F5 建置並執行應用程式。 按一下核取方塊以查看 FlowDirection 對應的效果。 按一下核取方塊時,配置的左右方向會顛倒。
請參閱
工作
逐步解說:在 WPF 中裝載 Windows Form 控制項