Это то, для чего предназначено внедрение зависимостей.
Прежде всего, если вы работаете с MVVM, вы должны иметь возможность запускать все приложение без создания каких-либо представлений вообще, то есть только моделей представлений.Если у вас есть MainWindow с ChildView (скажем), то в общем случае вы сопоставляете их с соответствующими моделями представлений:
public MainViewModel : ViewModeBase
{
public ChildViewModel MyChild {get; } // gets assigned later
Тогда в вашем XAML:
<Window ...
<local:ChildView DataContext="{Binding MyChild}" />
Иногда вам понадобитсяMyChild для отображения различных представлений, каждое из которых будет иметь свою собственную соответствующую модель представления, и вам может потребоваться изменить ее во время выполнения.В этих случаях MyChild должен иметь тип объекта (или некоторый общий базовый класс), а также должен поддерживать уведомление об изменении свойства:
public class MainViewModel : ViewModelBase
{
private object _MyChild;
public object MyChild
{
get { return this._MyChild; }
set
{
if (this._MyChild != value)
{
this._MyChild = value;
RaisePropertyChanged(() => this.MyChild);
}
}
}
}
Затем в вашем XAML вместо этого вы создаете ContentControl:
<Window ...
<ContentControl ="{Binding MyChild}" />
В этом месте вы затем используете DataTemplate в своем разделе ресурсов окна или приложения, чтобы указать, какие представления сопоставляются с какими моделями представлений:
<DataTemplate DataType="{x:Type vm:FooViewModel}">
<view:FooView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BarViewModel}">
<view:BarView />
</DataTemplate>
Так что теперь, если вы сделаете что-то подобное вваша MainViewModel ...
this.MyChild = new FooViewModel();
... ContentControl автоматически заполняется элементом управления типа FooView.Кроме того, его DataContext будет автоматически установлен на экземпляр FooViewModel, который вы создали.И затем вы переназначаете его следующим образом:
this.MyChild = new BarViewModel();
... тогда FooView будет заменен BarView.
Так что с DataTemplating все, что вам нужно беспокоиться, этоПередача ссылок на ваши ViewModel друг на друга, и здесь начинается внедрение зависимостей. Это большая тема, я предлагаю вам ознакомиться с ней, но идея в том, что вы создаете все свои модели представлений с помощью инфраструктуры DI (вместооператор new
) и пусть он склеит все биты вместе.Например, ваши продукты могут быть частью класса репозитория, который управляет всеми ними, поэтому вы начинаете с объявления интерфейса:
public interface IProductRepository
{
Products[] AllProducts();
Product GetProductByName(string name);
... etc ...
Затем вы создаете реальный класс, который реализует этот интерфейс, и во время установки выдайте вашей структуре зависимостей правила того, что она должна делать всякий раз, когда что-либо запрашивает IProductRepository (используйте один экземпляр, создайте новый и т. д.).Затем, когда что-либо во всем вашем приложении требуется для доступа к репозиторию продукта, все, что ему нужно сделать, это объявить свойство с тегом [Inject]
(это если вы используете Ninject, у каждой библиотеки есть свой способ сделать это):
public class MyClass
{
[Inject]
public IProductRepository ProductRepo {get; set;} // <-- gets injected
Теперь, когда вы создаете экземпляр типа MyClass, структура внедрения зависимостей создаст его для вас и автоматически инициализирует ProductRepo с использованием предоставленных вами правил.
Это очень простой обзоркак DataTemplating и Dependency Injection работают в MVVM, как только вы начнете использовать их, вы удивитесь, как раньше обходились без них.Насколько я могу судить, основная проблема в вашем вопросе заключается в том, что вы пытаетесь заставить ваши модели представлений общаться друг с другом.В общем, это не так, как реализован MVVM.Модели представлений обмениваются данными через сервисы, которые вводятся в них. Общее практическое правило заключается в том, чтобы служить проводником между этими сервисами и интерфейсными элементами графического интерфейса, а не друг с другом.