C# 将参数传递给ViewModel中的构造函数
我正在用MVVM模式构建一个WPF浏览器应用程序 我有一个带有数据网格的第一页(ConsultInvoice)。当我双击其中一行时,我想导航到另一个页面(EditInvoice),将参数中的选定行传递给我的构造函数 我知道如果我想把事情做好,我应该使用依赖注入,但我真的不知道如何在这里使用它 我如何简单地传递这个构造函数 咨询VoiceViewModelC# 将参数传递给ViewModel中的构造函数,c#,wpf,mvvm,dependency-injection,C#,Wpf,Mvvm,Dependency Injection,我正在用MVVM模式构建一个WPF浏览器应用程序 我有一个带有数据网格的第一页(ConsultInvoice)。当我双击其中一行时,我想导航到另一个页面(EditInvoice),将参数中的选定行传递给我的构造函数 我知道如果我想把事情做好,我应该使用依赖注入,但我真的不知道如何在这里使用它 我如何简单地传递这个构造函数 咨询VoiceViewModel private Invoice _selected; public Invoice Selected { get {
private Invoice _selected;
public Invoice Selected
{
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
private void Edit()
{
EditInvoiceViewModel editInvoice = new EditInvoiceViewModel(Selected);
/* doing something here*/
}
public ICommand EditCommand
{
get
{
return editCommand ?? (editCommand = new RelayCommand(p => this.Edit(), p => this.CanEdit()));
}
}
public class EditInvoiceViewModel : ViewModelBase
{
public Context ctx = new Context();
Invoice invoice;
PreInvoice preInvoice;
#region properties
private ObservableCollection<PreInvoice> collection;
public ObservableCollection<PreInvoice> Collection
{
get
{
return collection;
}
set
{
collection = value;
OnPropertyChanged("Collection");
}
}
#endregion
public EditInvoiceViewModel(Invoice inv)
{
/* do stuff*/
}
}
EditInvoiceViewModel
private Invoice _selected;
public Invoice Selected
{
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
private void Edit()
{
EditInvoiceViewModel editInvoice = new EditInvoiceViewModel(Selected);
/* doing something here*/
}
public ICommand EditCommand
{
get
{
return editCommand ?? (editCommand = new RelayCommand(p => this.Edit(), p => this.CanEdit()));
}
}
public class EditInvoiceViewModel : ViewModelBase
{
public Context ctx = new Context();
Invoice invoice;
PreInvoice preInvoice;
#region properties
private ObservableCollection<PreInvoice> collection;
public ObservableCollection<PreInvoice> Collection
{
get
{
return collection;
}
set
{
collection = value;
OnPropertyChanged("Collection");
}
}
#endregion
public EditInvoiceViewModel(Invoice inv)
{
/* do stuff*/
}
}
公共类EditInvoiceViewModel:ViewModelBase
{
公共上下文ctx=新上下文();
发票;
预发票预发票;
#区域属性
私人收藏;
公开收集
{
得到
{
回收;
}
设置
{
收集=价值;
不动产变更(“收款”);
}
}
#端区
public EditInvoiceViewModel(发票库存)
{
/*做事*/
}
}
基本上,您应该避免将此类参数传递到ViewModels构造函数中,因为将其与控制反转/依赖注入相连接会让人感到痛苦。虽然您可以使用抽象工厂模式来解析带有运行时参数的对象,但它并不适用于ViewModels 相反,我总是建议使用一种形式的导航模式,类似于微软的模式与实践团队使用Prism所做的。在这里,您可以实现一个
INavigationAware
界面。它有两种方法,NavigateTo
和NavigateFrom
还有导航服务。导航服务将切换视图,然后在当前视图模型中切换调用NavigateFrom
(如果它实现了它。可以使用它检查是否保存了数据,如有必要,取消导航。加载新视图并为其分配ViewModel后,在新导航的ViewModel中调用NavigateTo
)
在这里,您可以传递ViewModel所需的参数,在您的情况下是invoiceId
。尽量避免传递整个模型或复杂对象。使用invoiceId
获取发票数据并填充编辑的ViewModel
我以前的回答中的一个基本实现(可以找到):
INavigationService公共接口
{
//T是基础ViewModel类的名称
void NavigateTo(),其中T ViewModel;
void NavigateToNewWindow();
void NavigateToNewWindow(对象参数);
void NavigateTo(对象参数);
}
公共类导航服务:INavigationService
{
专用IUnityContainer容器;
公共导航服务(IUnityContainer容器)
{
this.container=容器;
}
public void NavigateToWindow(对象参数),其中T:IView
{
//配置IoC容器以解析给定ViewModel的视图
//即容器。在您的
//成分根
IView view=container.Resolve();
视窗视窗=视窗;
如果(窗口!=null)
window.Show();
INavigationAware导航=查看为INavigationAware;
如果(导航!=null)
导航到(参数);
}
}
//IPlotView是一个空接口,仅用于能够解析
//PlotWindow不需要参考其具体实现,如下所示
//调用navigationService.NavigateToWindow(userId);将违反
//MVVM模式,其中navigationService.NavigateToWindow(userId)不支持。还有其他涉及字符串或命名的方法
//常规,但这超出了这个答案的范围。我会的
//只需实现“objectdatacontext{get;set;}”属性,该属性已经存在
//实现的控制对象
公共类绘图窗口:窗口、IView、IPlotView
{
}
公共类PlotViewModel:ViewModel、INotifyPropertyChanged、INavigationAware
{
私有int plotId;
public void导航到(对象参数),其中T:IView
{
如果(!参数为int)
return;//传递了错误的参数类型
this.plotId=(int)参数;
任务。开始(()=>{
//加载数据
PlotData=加载图(plotId);
});
}
私有绘图数据;
公共绘图数据{
获取{return plotData;}
设置
{
if(plotData!=值)
{
plotData=值;
OnPropertyChanged(“绘图数据”);
}
}
}
}
Prism中使用的INavigationAware
接口示例可在上找到
这使得传递参数和
async
加载数据变得很容易(没有任何干净的方法通过构造函数来实现,因为你不能等待构造函数中的async
操作而不锁定,在构造函数中做这种事情是非常不受欢迎的).可能只有我一个人,但我有点困惑。您不是已经在ViewModel(ConsultInvoiceViewModel)中向构造函数(EditInvoiceViewModel(Invoice inv))传递了一个参数(选定的)吗?你到底在问什么?@Rowbear是的,但目标是打开一个新的EditInvoiceView.xaml,并且它只接受一个默认构造函数。所以我试图做的不起作用。啊!我明白了。你打算让EditInvoiceView显示为一个弹出窗口还是一个新窗口?你打算如何控制EditInvoiceView的显示?仅使用.show()/.ShowDialog()?ConsultInvoiceViewModel中所有可能的发票共享一个视图有意义吗?或者您可以一次编辑多个发票吗?@Rowbear,我计划将其显示为一个新窗口,但弹出窗口也可以。在我不知道如何导航之后。这就是重点。在我的其他页面之间,我使用Hyperlink.B