从ViewModel中打开一个窗口窗体

本文关键字:一个 窗口 窗体 ViewModel | 更新日期: 2023-09-27 18:16:34

我正在开发一个遗留产品,到目前为止,它的所有内容都是使用windows窗体制作的。由于需要大量使用xml,所以我使用WPF,因为它易于绑定。我正在使用MVVM模型,因为需求需要不同的视图,但业务逻辑没有太大差异。我有一个用户控件,它有一个打开windows窗体的按钮。这个用户控件在不同的windows窗体上。

这是我的xaml与按钮相关的代码:

<UserControl x:Name="ctrlTemplate" x:Class= "CtrlTemplate"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFControl.UI"
             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:xckt="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
             mc:Ignorable="d" 
             DataContext="{DynamicResource ViewModel}">
    <UserControl.Resources>
            <local:ViewModel x:Key="ViewModel" />
        </ResourceDictionary>
    </UserControl.Resources>

下面是与

按钮绑定的命令
<Button x:Name="btnOpenWindowsUI" Command="{Binding OpenWindowsUI, Source={StaticResource ViewModel}}" CommandParameter={????} >

我的ViewModel是这样的

public class ViewModel : ViewModelBase
{
    public ICommand OpenWindowsUI{ get; set; }
    public OTCViewModel()
    {
        OpenWindowsUI= new OpenWindowsUI(this);
    }
}

我的命令是这样的:

class OpenWindowsUI: ICommand
{
    private ViewModel _mvModel;
    public event EventHandler CanExecuteChanged
    {
        add { }
        remove { }
    }
    public ClearAllData(ViewModel mvModel)
    {
        _mvModel = mvModel;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public void Execute(object parameter)
    {
        IWindowsUI indowsUIInstance = null;
        windowsUIInstance = _container.Resolve<IWindowsUI >();
        frmWindowsUI = windowsUIInstance.Reference();
        frmWindowsUI.Owner = this; **//How can we specify the parent of this chid form?**
        frmWindowsUI.ShowInTaskbar = false;
        windowsUIInstance.SetUp();
        frmWindowsUI.Show();
        frmWindowsUI.FormClosed += frmWindowsUI_FormClosed;
    }
}

我知道可以很容易地从usercontrol代码中找到父窗体,使用下面的代码片段:

public Form FindParentWindowsForm()
{
    var source = (HwndSource)PresentationSource.FromDependencyObject(btnOpenWindowsUI);
    Form form;
    if (source != null)
    {
        var host = (System.Windows.Forms.Integration.ElementHost)System.Windows.Forms.Control.FromChildHandle(source.Handle);
        if (host != null)
        {
             form = (Form)host.TopLevelControl;
        }
    }
    return form;
}

我的问题是:

  1. 是否有一种方法将UI元素从控件传递到ViewModel?

  2. 我们应该把一个UI元素的引用传递给ViewModel吗?

  3. 如果不是,解决上述问题的最佳方法是什么?

从ViewModel中打开一个窗口窗体

我没有完整的解决方案。

。1。是的,你可以-例如下面的代码将传递整个窗口对象作为CommandParameter:

    <button [...] CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>

。2。这个问题是典型的MVVM辩论的主题。一方面,UIElement只是一个对象,它在高级视图中与其他对象(如属性)没有真正的不同,但另一方面,传递UIElement作为参数有点破坏MVVM,因为从这一刻起ViewModel将意识到视图。

。3。

  1. 。你不应该把UI元素传递给MVVM中的ViewModel。
  2. 您可以创建一个单独的控件并将其绑定到视图。在控件中创建一些依赖属性。通过ViewModel更改属性的值。当你可以改变这个值时,控件就会被调用依赖属性,现在窗口中就有了控件的可视树。

请参考http://social.technet.microsoft.com/wiki/contents/articles/31416.wpf-mvvm-friendly-user-notification.aspx#ConfirmationRequestor