В принципе вы должны избегать прохождения таких параметров в конструктор ViewModels, так как проводка его Инверсия управления/Dependency Injection становится боль. Хотя вы можете использовать шаблон Abstract Factory для разрешения объектов с параметрами времени выполнения, это imho не подходит для ViewModels.
Вместо этого я всегда предлагаю использовать форму навигации, похожую на то, как шаблоны Microsoft & Практика команда сделала с Prism. Там у вас есть интерфейс INavigationAware
, который можно реализовать в ViewModels. Он имеет 2 метода: NavigateTo
и NavigateFrom
.
И есть навигационное обслуживание. Навигационная служба переключит представления и до переключения вызова NavigateFrom
в текущую ViewModel (если она ее реализует). Можно использовать ее, чтобы проверить, сохранены ли данные и, при необходимости, отменить навигацию. После того, как новый просмотр был загружен и назначен ViewModel к нему, называем NavigateTo
в недавно ViewModel управление судном.
Здесь вы бы передать параметры, необходимые для ViewModel, в вашем случае invoiceId
. Старайтесь избегать прохождений целых моделей или сложных объектов. Используйте invoiceid
для извлечения данных счетов и для заполнения вашего редактирования ViewModel.
Реализация базового элемента из моего прежнего ответа (вы можете найти here):
public interface INavigationService
{
// T is whatever your base ViewModel class is called
void NavigateTo<T>() where T ViewModel;
void NavigateToNewWindow<T>();
void NavigateToNewWindow<T>(object parameter);
void NavigateTo<T>(object parameter);
}
public class NavigationService : INavigationService
{
private IUnityContainer container;
public NavigationService(IUnityContainer container)
{
this.container = container;
}
public void NavigateToWindow<T>(object parameter) where T : IView
{
// configure your IoC container to resolve a View for a given ViewModel
// i.e. container.Register<IPlotView, PlotWindow>(); in your
// composition root
IView view = container.Resolve<T>();
Window window = view as Window;
if(window!=null)
window.Show();
INavigationAware nav = view as INavigationAware;
if(nav!= null)
nav.NavigatedTo(parameter);
}
}
// IPlotView is an empty interface, only used to be able to resolve
// the PlotWindow w/o needing to reference to it's concrete implementation as
// calling navigationService.NavigateToWindow<PlotWindow>(userId); would violate
// MVVM pattern, where navigationService.NavigateToWindow<IPlotWindow>(userId); doesn't. There are also other ways involving strings or naming
// convention, but this is out of scope for this answer. IView would
// just implement "object DataContext { get; set; }" property, which is already
// implemented Control objects
public class PlotWindow : Window, IView, IPlotView
{
}
public class PlotViewModel : ViewModel, INotifyPropertyChanged, INavigationAware
{
private int plotId;
public void NavigatedTo(object parameter) where T : IView
{
if(!parameter is int)
return; // Wrong parameter type passed
this.plotId = (int)parameter;
Task.Start(() => {
// load the data
PlotData = LoadPlot(plotId);
});
}
private Plot plotData;
public Plot PlotData {
get { return plotData; }
set
{
if(plotData != value)
{
plotData = value;
OnPropertyChanged("PlotData");
}
}
}
}
Пример интерфейса INavigationAware
, используемого в Prism можно найти на projects github repository.
Это позволяет легко передавать параметр и async
загрузить данные (там, где нет никакого чистый способ сделать это с помощью конструктора, так как вы не можете await
async
операции внутри конструктора без блокировки, и делает этот вид вещей в конструкторе очень обескуражен).
Возможно, это только я, но я немного смущен. Вы уже передаете параметр (Selected) в конструктор (EditInvoiceViewModel (Invoice inv)) в ViewModel (ConsultInvoiceViewModel)? Что именно вы спрашиваете? – Rowbear
@Rowbear да, но целью является открытие нового EditInvoiceView.xaml, и он принимает только конструктор по умолчанию. То, что я пытаюсь сделать, не работает. – Cantinou
ах! Понимаю. Вы планируете показывать EditInvoiceView как всплывающее окно или новое окно?Как вы планируете контролировать показ EditInvoiceView? С помощью только .Show() /. ShowDialog()? Имеет ли смысл использовать все возможные счета от ConsultInvoiceViewModel для совместного использования одного вида? Или вы сможете редактировать сразу несколько счетов-фактур? – Rowbear