无法绑定到属于C#/ XAML应用程序中的WindowsFormsHost子对象的属性的解决方法?

我有一个C#WPF 4.51应用程序。 据我所知,您不能绑定属于作为WPF WindowsFormsHost控件的子对象的属性。 (如果我在这个假设中错了,请告诉我该怎么做):

与WindowsFormsHost绑定

在我的例子中,我有一个包含WindowsFormsHost控件的页面,其Child对象是ScintillaNET编辑器控件:

https://github.com/jacobslusser/ScintillaNET

     

子控件工作正常。 如果它是一个普通的WPF控件,我会将Scintilla编辑器控件的Text属性绑定到我的ViewModel中的某个字符串属性,这样我只需更新Scintilla编辑器控件的内容即可更新该字符串属性。

但由于我无法绑定属于WindowsFormsHost子对象的属性,我正在寻找一种不完全笨拙或笨拙的策略/解决方案。 有没有人以前遇到过这种情况,并且有一个合理的策略来解决我的绑定/更新问题?

这里一个简单的方法是,您可以创建一些专用类,以包含映射到winforms控件中的属性的附加属性。 在这种情况下,我只选择Text作为示例。 使用这种方法,您仍然可以正常设置Binding,但附加属性将在WindowsFormsHost

 public static class WindowsFormsHostMap { public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached("Text", typeof(string), typeof(WindowsFormsHostMap), new PropertyMetadata(propertyChanged)); public static string GetText(WindowsFormsHost o) { return (string)o.GetValue(TextProperty); } public static void SetText(WindowsFormsHost o, string value) { o.SetValue(TextProperty, value); } static void propertyChanged(object sender, DependencyPropertyChangedEventArgs e) { var t = (sender as WindowsFormsHost).Child as Scintilla; if(t != null) t.Text = Convert.ToString(e.NewValue); } } 

在XAML中的用法

      

Child当然应该是Scintilla ,否则你需要修改WindowsFormsHostMap的代码。 无论如何,这只是为了展示这个想法,你总是可以调整它以使其更好。

请注意,上面的代码仅适用于单向绑定(从视图模型到winforms控件)。 如果您想要另一种方式,则需要为控件注册一些事件处理程序,并将值更新回该处理程序中的附加属性。 这种方式非常复杂。

您只能使用Windows窗体控件实现非常非常有限的绑定,因为绑定不会接收更新通知,并且可能需要显式轮询以通过自定义RefreshValues()方法或轮询每个数据的内容来获取结果。

但是,如果你只需要访问子控件,你应该在代码中进行绑定:

 (WFH.Child as MyWinFormsControl).Text 

如果你打算做很多绑定,可能更容易创建一个WPF包装器对象(也许是UserControl ),它具有你需要的所有属性作为DependencyProperties和底层代码,每个属性都会手动轮询WinForms控件,就好像它是该物业的支持领域。 它起初有点复杂,但比手动轮询每个属性更容易。

创建Windows窗体主机类型的依赖对象。

 using System.Windows.Forms.Integration; namespace MainStartUp.DependencyObjects { public class FormHostDependencyObject : WindowsFormsHost { public static readonly DependencyProperty ContentControlProperty = DependencyProperty.Register("ContentControl", typeof(System.Windows.Forms.Control), typeof(FormHostDependencyObject), new PropertyMetadata(new System.Windows.Forms.Control(), PropertyChaged)); public static void SetContentControl(UIElement element, string value) { element.SetValue(ContentControlProperty, value); } public static string GetContentControl(UIElement element) { return (string)element.GetValue(ContentControlProperty); } private static void PropertyChaged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { ((FormHostDependencyObject)dependencyObject).Child = (System.Windows.Forms.Control)e.NewValue; } } }