繁体   English   中英

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

[英]Workaround for inability to bind to a property that belongs to a WindowsFormsHost Child object in C#/XAML app?

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

与WindowsFormsHost绑定

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

https://github.com/jacobslusser/ScintillaNET

    <WindowsFormsHost x:Name="wfhScintillaTest"
                      Width="625"
                      Height="489"
                      Margin="206,98,0,0"
                      HorizontalAlignment="Left"
                      VerticalAlignment="Top">
        <WindowsFormsHost.Child>
            <sci:Scintilla x:Name="scintillaCtl" />
        </WindowsFormsHost.Child>
    </WindowsFormsHost>

子控件工作正常。 如果它是一个普通的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中的用法

<WindowsFormsHost x:Name="wfhScintillaTest"
                  Width="625"
                  Height="489"
                  Margin="206,98,0,0"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  local:WindowsFormsHostMap.Text="{Binding yourTextProp}"
    >
    <WindowsFormsHost.Child>
        <sci:Scintilla x:Name="scintillaCtl"/>
    </WindowsFormsHost.Child>
</WindowsFormsHost>

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;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM