我正在使用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();
//}
}
答案 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"/>