简体   繁体   English

在WPF中使用MVVM模式创建对话框时,如何实例化对话框并记录用户输入

[英]How to instantiate a dialog and record user input while MVVM pattern is used to create dialog in WPF

I am a C++ developer and new to WPF and MVVM. 我是C ++开发人员,并且是WPF和MVVM的新手。 please bear with me if I choose any wrong word to ask my question 如果我选择了错误的单词问我的问题,请忍受我

I have my Main application in MFC/C++ which is passing some data to C# library( CLI is used as middle layer). 我在MFC / C ++中有我的Main应用程序,该应用程序将一些数据传递给C#库( CLI被用作中间层)。 In C# library , there is a section of code where a dialog is opened , data is filled and user selection is notified to the calling object in below way - C#库中 ,有一段代码可以打开对话框,填充数据,并通过以下方式将用户选择通知给调用对象:

public classA()
{
    MyDialog dlg = new MyDialog(param1, param2, param3)
    if(dlg.ShowDialog().GetValueOrDefault())
    {
        var name = dlg.name;
        var roll = dlg.roll;
    }
    else
    {
        var name = string.Empty;
        var roll = string.Empty;
    }
}

Now Dialog has been modified and implemented using MVVM pattern. 现在,Dialog已被修改并使用MVVM模式实现。

I have created below files as part of implementation- 1 我已将以下文件创建为实施的一部分-1

  1. MyDialogView.Xaml MyDialogView.Xaml
  2. MyDialogView.xaml.cs MyDialogView.xaml.cs
  3. MyDialogViewModel.cs MyDialogViewModel.cs
  4. MyDialogModel.cs MyDialogModel.cs

My question is, how to instantiate the new dialog now from my classA so that data is filled using the parameters passed to dialog in same way as previously it was doing and record user selection without loosing any data and safely closing the view. 我的问题是,现在如何从我的classA实例化新对话框,以便使用传递给对话框的参数以与以前相同的方式填充数据,并记录用户选择,而不会丢失任何数据并安全地关闭视图。

Standard MVVM approach works like this (at least when using MVVM Light): 标准MVVM方法的工作方式如下(至少在使用MVVM Light时):

  1. You have a VM layer, a Class Library. 您有一个VM层,一个类库。
  2. You have a View layer, a WPF Controls Library or WPF Application. 您有一个View层,一个WPF控件库或WPF应用程序。
  3. View layer adds reference to VM layer. 视图层添加了对VM层的引用。 VM layer doesn't know anything about View. VM层对View一无所知。
  4. You create a normal public class for your dialog's VM. 您为对话框的VM创建一个普通的公共类。 Call it DialogVM or whatever. 称之为DialogVM或其他名称。 Make sure this class inherits from MVVM Light's built-in ViewModelBase . 确保此类继承自MVVM Light的内置ViewModelBase This will get you access to change notification methods provided by MVVM Light. 这将使您能够访问MVVM Light提供的更改通知方法。 Might look like this in your case: 在您的情况下,可能看起来像这样:

     public partial class DialogVM : ViewModelBase { private string _Name; public string Name { get { return _Name; } set { Set(ref _Name, value); } } private string _Roll; public string Roll { get { return _Roll; } set { Set(ref _Roll, value); } } } 
  5. VM layer has a global static class called ViewModelLocator . VM层具有一个称为ViewModelLocator的全局静态类。 This class performs IoC/DI and provides public static properties to expose different VMs. 此类执行IoC / DI,并提供公共静态属性以公开不同的VM。 (In your case your dialog's VM goes to the VM project and the ViewModelLocator looks something like this: (在您的情况下,对话框的VM转到VM项目,并且ViewModelLocator看起来像这样:

     using System; namespace VMLayer { public class ViewModelLocator { static ViewModelLocator() { SimpleIoc.Default.Register<DialogVM>(true); } public static DialogVM MyDialog => SimpleIoc.Default.GetInstance<DialogVM>(); } } 
  6. Your dialog box (a Window ) goes to View layer and uses this exposed property MyDialog to provide a DataContext for the dialog: 您的对话框( Window )转到“视图”层,并使用此公开的属性MyDialog为对话框提供DataContext

     <Window x:Class="GlasshouseTestingShell.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:vm="clr-namespace:VMLayer;assembly=VMLayer" DataContext="{x:Static vm:ViewModelLocator.MyDialog}" d:DataContext="{d:DesignInstance Type=vm:DialogVM}"> </Window> 
  7. Look how cleanly we have created View layer's DataContext without writing a line of C# code in the View layer. 看看我们如何干净地创建View层的DataContext而不在View层中编写C#代码行。 This is also elegant in the sense that you get all design-time Intellisense in Binding expressions and elsewhere. Binding表达式和其他地方都获得了所有设计时Intellisense的意义上,这也很优雅。
  8. You now bind all your UI stuff (textboxes, buttons etc.) to the public properties and commands exposed by your dialog's VM. 现在,您将所有UI内容(文本框,按钮等)绑定到对话框VM公开的公共属性和命令。 Still no lines in the code-behind. 后面的代码中仍然没有一行。 Might look like this in your case: 在您的情况下,可能看起来像这样:

     <TextBox Text="{Binding Name}" /> 

Rest of the stuff is in C++: 其余的东西在C ++中:

  1. You add reference to your View and VM DLLs in your C++ project. 您可以在C ++项目中添加对View和VM DLL的引用。
  2. Create an object of your dialog. 创建对话框的对象。 It will automatically instantiate its VM and perform binding. 它将自动实例化其VM并执行绑定。 You call ShowDialog() to bring it to screen. 您调用ShowDialog()使其显示在屏幕上。
  3. Use takes actions in the dialog and finally presses OK or Cancel. 使用在对话框中执行操作,最后按确定或取消。
  4. You capture dialog result and then access your dialog object's DataContext property, which is an object of DialogVM class. 您捕获对话框结果,然后访问对话框对象的DataContext属性,该属性是DialogVM类的对象。 You can access user-supplied values from therein as Binding has updated those properties for you in the VM. 您可以从中访问用户提供的值,因为绑定已在VM中为您更新了这些属性。

I'm not sure I follow all of your requirements but this is roughly how I'd approach such a task: 我不确定我是否会遵循您的所有要求,但这大致就是我将要完成的任务的方式:

Instantiate the view and viewmodel in class A. 实例化类A中的视图和视图模型。

Set whatever parameters you want on your viewmodel. 在视图模型上设置所需的任何参数。 Either as properties or via constructor injection. 作为属性或通过构造函数注入。

Set the datacontext of the view to the viewmodel. 将视图的datacontext设置为viewmodel。

Everything you need to bind should then bind between them. 然后,您需要绑定的所有内容都应在它们之间进行绑定。

showdialog the view. showdialog视图。

The user edits in the view and changes persist to the viewmodel properties. 用户在视图中进行编辑,更改将保留在viewmodel属性中。

They finish editing and you then work with the viewmodel properties. 他们完成了编辑,然后您可以使用viewmodel属性。 Maybe one of them is the model you mention. 也许其中之一就是您提到的模型。 Maybe the model is instantiated by the viewmodel to get data or by classA if that is more convenient. 也许是由视图模型实例化模型以获取数据,或者如果更方便,则由classA实例化。 In the latter case you probably have to pass that model to the viewmodel. 在后一种情况下,您可能必须将该模型传递给viewmodel。

Bearing in mind the above. 牢记以上内容。

Some rough code: 一些粗略的代码:

public class ClassA
{
    MyDialogViewModel vm = new MyDialogViewModel { Name = "X", Roll = "Y" };
    MyDialog dlg = new MyDialog();
    dlg.ShowDialog();
    var name = vm.Name;
    var roll = vm.roll;

    // Do something to persist your data as necessary. Either here or in a model within the viewmodel
}

Name and Roll presumably bind to some textboxes Text properties in the view or some such. 名称和滚动可能绑定到视图中的某些文本框或某些文本属性。

If it's as simple as obtaining two string values then I see no advantage to actually having a model at all. 如果只是简单地获得两个字符串值,那么我认为实际上拥有一个模型根本没有任何好处。 On the other hand, if processing is more involved then of course the viewmodel might instantiate a model. 另一方面,如果更多地涉及处理,那么视图模型当然可以实例化模型。

MyDialogViewModel should implement inotifypropertychanged and anything you need to bind should be a public property. MyDialogViewModel应该实现inotifypropertychanged,并且您需要绑定的任何东西都应该是公共属性。 Not sure if you'll need propertychanged notification but always implement it. 不知道您是否需要属性更改通知,但始终执行它。 Optionally raise propertychanged from property setters. (可选)提高从属性设置器更改的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM