For a WPF application I’m currently working on, I need to use a legacy Windows Form control. This legacy control has a public function which takes in a complex POCO to do its magic. My WPF view-model handles the creation of this POCO and I need to somehow find a way to bind this POCO created by the view-model to the legacy Windows Form control.
Let’s illustrate this with a very simple example.
In my WPF window I want to reuse a Windows Form control that takes in aSteps to solve in a nutshell:
1) Wrap the Windows Form control in a WPF control using WindowsFormsHost
2) Add DependencyProperty of type POCO to the WPF control
3) In WPF main window, add the WPF control and bind the DependencyProperty to property of type POCO in the view-model
The Windows Form Control
The Windows Form control has a public function that takes in a
namespace WfControlHostedInWpfControl {using System;using System.Windows.Forms;public partial class WindowsFormControl :UserControl {public WindowsFormControl() { InitializeComponent(); }public void WorkYourMagic(Person person) { TextBoxName.Text = person.Name; TextBoxAge.Text =Convert .ToString(person.Age); } } }
The POCO
namespace WfControlHostedInWpfControl {public class Person {public string Name {get ;set ; }public int Age {get ;set ; } } }
The WPF Control
The WPF control is a wrapper around the Windows Form control.
The XAML is very simple. It only contains a
< UserControl x :Class ="WfControlHostedInWpfControl.WpfControl"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"xmlns :local ="clr-namespace:WfControlHostedInWpfControl"mc :Ignorable ="d"d :DesignHeight ="300"d :DesignWidth ="300"> <WindowsFormsHost Name ="MyHost"> <local:WindowsFormControl /> </WindowsFormsHost > </UserControl >
In the code behind, we retrieve the original Windows Form Control by calling the Child property of
namespace WfControlHostedInWpfControl {using System.Windows;using System.Windows.Controls;public partial class WpfControl :UserControl {public static readonly DependencyProperty ComplexPocoProperty =DependencyProperty .Register("ComplexPoco" ,typeof (Person ),typeof (WpfControl ),new FrameworkPropertyMetadata (default (Person ),FrameworkPropertyMetadataOptions .BindsTwoWayByDefault, OnPropertyChanged));public Person ComplexPoco {get {return (Person )GetValue(ComplexPocoProperty); }set { SetValue(ComplexPocoProperty,value ); } }private static void OnPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) {WpfControl thisControl = (WpfControl )d;WindowsFormsHost wfHost = thisControl.MyHost;WindowsFormControl wf = (WindowsFormControl )wfHost.Child; wf.WorkYourMagic((Person )e.NewValue); }public WpfControl() { InitializeComponent(); } } }
The WPF Main Window
< Window x :Class ="WfControlHostedInWpfControl.MainWindow"xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns :x ="http://schemas.microsoft.com/winfx/2006/xaml"xmlns :local ="clr-namespace:WfControlHostedInWpfControl"Title ="MainWindow"Height ="200"Width ="300"> <StackPanel > <local:WpfControl ComplexPoco ="{Binding Person }" /> <Button Content ="Show me the magic!"Command ="{Binding ShowMagic }" /> </StackPanel > </Window >
Here we initialize
Code behind:
namespace WfControlHostedInWpfControl {using System.Windows;public partial class MainWindow :Window {public MainWindow() { InitializeComponent(); DataContext =new ViewModel (); } } }
The view-model:
namespace WfControlHostedInWpfControl {using System;using System.Collections.Generic;using System.ComponentModel;using System.Windows.Input;public class ViewModel :INotifyPropertyChanged {private Person person;private readonly List <Person > repository;public ViewModel() { repository =new List<Person > {new Person { Name ="John" , Age = 20 },new Person { Name ="Amber" , Age = 24 },new Person { Name ="Sally" , Age = 30 },new Person { Name ="Abe" , Age = 50 } }; ShowMagic =new RelayCommand (PickRandomPerson); }public Person Person {get {return person; }set { person =value ; OnPropertyChanged("Person" ); } }public ICommand ShowMagic {get ;set ; }public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName) {if (PropertyChanged !=null ) PropertyChanged(this ,new PropertyChangedEventArgs (propertyName)); }private void PickRandomPerson() {int index =new Random ().Next(0, repository.Count); Person = repository[index]; } } }
There you have it! A simplified toy example of the actual problem I was dealing with.
No comments:
Post a Comment