WPF MVVM WinformsHost与OpenGL控件

3
我正在开发一个使用MVVM的WPF应用程序。在这个应用程序中,我需要一个OpenGL控件(我正在使用OpenTK)。目前唯一有用的将OpenGL嵌入到WPF中的方法是使用WindowsFormsHost。到此为止,没有问题。
为了向我的场景添加内容,我需要在视图中访问OpenGL控件。当然,我想在ViewModel中添加和编辑内容。那么,如何在不违反MVVM模式的情况下访问OpenGL控件呢?
我正在使用一个场景对象,可以在视图中初始化,然后需要以某种方式传输到ViewModel中。我尝试使用WindowsFormsHost的Tag属性来实现,但没有成功(请参见下文)。ViewModel中的属性没有被更新。
有什么想法吗?
XAML
<UserControl x:Class="FancyOpenGlControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">    
    <WindowsFormsHost x:Name="WindowsFormsHost" Tag="{Binding Scene, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</UserControl>

C#

public FancyOpenGlControl()
{
    this.InitializeComponent();

    this.glControl = new OpenGLControl();
    this.glControl.Dock = DockStyle.Fill;
    this.WindowsFormsHost.Child = this.glControl;

    this.glControl.HandleCreated += this.GlControlOnHandleCreated;
}

private void GlControlOnHandleCreated(object sender, EventArgs eventArgs)
{
    this.WindowsFormsHost.Tag = new Scene(this.glControl);

    // Doesn't work.
    //BindingExpression bindingExpression = this.WindowsFormsHost.GetBindingExpression(TagProperty);
    //if (bindingExpression != null)
    //{
    //    bindingExpression.UpdateSource();
    //}
}

你是否检查过你的视图和视图模型是否正确绑定了? - Dhaval Patel
我在HandleCreated事件中检查了DataContext属性,它是我的ViewModel的一个实例。所以我想这个工作正常。 - freakinpenguin
1个回答

2

我能想到两个选项。

1)从视图代码后台直接设置您的ViewModel属性。由于在视图的构造函数中您的ViewModel还没有连接,因此您需要在响应视图的DataContextChanged事件时执行此操作。这也意味着将DataContext转换为已知类型的ViewModel。我对此没有太大问题,但有些人可能会有异议。

private void FancyOpenGlControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    var vm = this.DataContext as MyViewModel;

    if (vm != null)
        vm.GlControl = this.glControl;
}

2)如果您更喜欢较松散的耦合,则可以在视图上创建一个依赖属性,并在创建时将glControl分配给该属性。然后,您可以像正常情况下一样将该属性绑定到任何ViewModel属性。例如:

代码后台:

public static readonly new DependencyProperty GControlProperty =
    DependencyProperty.Register("GLControl", typeof(OpenGLControl), typeof(FancyOpenGlControl), new PropertyMetadata(null));

public OpenGLControl GLControl
{
    get { return (OpenGLControl )GetValue(DocumentProperty); }
    set { SetValue(GLControlProperty , value); }
}

public FancyOpenGlControl()
{
    this.InitializeComponent();

    this.GLControl= new OpenGLControl();
    this.GLControl.Dock = DockStyle.Fill;
    this.WindowsFormsHost.Child = this.GLControl;
}

XAML:

<UserControl x:Class="FancyOpenGlControl"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            GLControl="{Binding VMControlProperty}">    
    <WindowsFormsHost x:Name="WindowsFormsHost"/>


1
谢谢Gaz,第二个解决方案非常好。我一直在使用第一个,但从我的角度来看,这破坏了MVVM模式!感谢您的详细说明! - freakinpenguin
感谢解决方案1,非常适合我。在DataTemplate更改后,需要将一个项目从视图传递到视图模型。 - Jeff Anderson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接