[英]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
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时):
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); } } }
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>(); } }
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>
DataContext
without writing a line of C# code in the View layer. DataContext
而不在View层中编写C#代码行。 This is also elegant in the sense that you get all design-time Intellisense in Binding
expressions and elsewhere. Binding
表达式和其他地方都获得了所有设计时Intellisense的意义上,这也很优雅。 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 ++中:
ShowDialog()
to bring it to screen. ShowDialog()
使其显示在屏幕上。 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. 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.