从ViewModel打开一个窗体

时间:2015-10-08 12:12:06

标签: c# wpf forms xaml mvvm

我正在开发一种传统产品,迄今为止所有产品都是使用Windows窗体制作的。由于涉及大量使用XML的要求,我使用WPF因为它易于绑定。我正在使用MVVM模型,因为需求需要不同的视图,但业务逻辑没有太大区别。 我有一个用户控件,它有一个用于打开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. 如果不是解决上述问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

我没有为你提供完整的解决方案:

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

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

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

0.3。您是否可以访问要以任何方式传递给用户控件的元素?

答案 1 :(得分:0)

  1. 是的,你可以。
  2. 否。您不应该将UI元素传递给MVVM中的ViewModel。
  3. 您可以创建一个单独的控件并将其绑定到视图。在控件中创建一些依赖项属性。通过ViewModel更改属性的值。由于您可以更改该值,因此控件将获取调用的依赖项属性,该属性现在在窗口中具有可视控件树。
  4. 请参阅http://social.technet.microsoft.com/wiki/contents/articles/31416.wpf-mvvm-friendly-user-notification.aspx#ConfirmationRequestor