使用OpenGL-Control的WPF MVVM WinformsHost

时间:2014-05-19 09:07:04

标签: c# wpf opengl mvvm opentk

我正在使用MVVM开发WPF应用程序。在这个应用程序中,我需要一个OpenGL控件(我正在使用OpenTK)。目前在WPF中获取OpenGL的唯一有用方法是使用WindowsFormsHost。直到这里,没有问题。

要向我的场景添加内容,我需要在我的视图中访问OpenGL-Control。当然,我想在ViewModel中添加和编辑内容。那么,如何在不违反MVVM模式的情况下访问OpenGL-Control?

我正在使用一个可以在View中初始化的场景对象,然后需要以某种方式转移到ViewModel。我尝试使用WindowsFormsHost的Tag-property但没有成功(比较如下)。 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();
    //}
}

1 个答案:

答案 0 :(得分:2)

我能想到两种选择。

1)直接从后面的视图代码设置viewmodel属性。您需要执行此操作以响应视图的DataContextChanged事件,因为您的ViewModel尚未在视图的构造函数中连接。这也意味着将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"/>