Как избежать связывания представлений XAML для запуска кода в приложении WPF MVVM? - PullRequest
1 голос
/ 05 января 2011

Мне действительно нравится гибкость объявления моей ViewModel в DataContext для View через XAML, но мне трудно понять, как я могу связать эту ViewModel с остальной частью системы.

Ex.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ViewModels">

<Window.DataContext>
    <local:MainViewModel />
</Window.DataContext>    

Проблема здесь в том, что мои ViewModels часто будут иметь и обмениваться зависимостями с другими частями системы, и я не уверен, как я могу вставить ссылку на другой объект в объявленную выше MainViewModel.

Если бы я делал ручную сортировку зависимостей, то при запуске приложения я бы создал несколько фабрик, отвечающих за все.

Как я могу использовать этот же подход в приложении MVFM WPF? И какой самый эффективный способ справиться со всеми моими ViewModels?

Ответы [ 5 ]

2 голосов
/ 06 января 2011

Чтобы добиться полной развязки, установите ViewModels на ResourceDictionary, найденный в основном классе приложения.Есть два способа сделать это, и по большей части не имеет значения, какой метод используется.Однако есть и компромиссы.

Метод 1

Если это делается программно, вы должны убедиться, что ключи словаря совпадают.Это вызывает слабую связь между строками, определенными в XAML, и теми, которые определены программно.Не идеал, но и не конец света.Преимущество здесь в том, что можно использовать конструктор инъекций.

//App.xaml.cs
//This line invoked somewhere after App OnStartUp function is called. 
MainViewModel mainViewModel = new MainViewModel( new Dependency() );
Current.ResourceDictionary["MainViewModel"] = mainViewModel; 

//MainView.xaml
<Window DataContext="{StaticResource MainViewModel}">

Бизнес-логике не важно, что такое View, и приложение может быть загружено любым способом ... с использованием объекта фабрики / компоновщика или любого контейнера IOC.(Пока все начинается в функции OnStartUp).

Метод 2

Определение моделей представления в App.xaml с использованием Application.Resource.Используя этот метод, все имена ключей будут расположены в XAML, что выглядит довольно неплохо.Единственным отрицательным результатом является то, что .NET автоматически создает ViewModels, заставляя их предоставлять конструкторы по умолчанию.Иногда желательно, чтобы контейнер IOC создавал ваши объекты или использовал Constructor Injection на пользовательских фабриках / сборщиках.

//App.xaml
<Application 
    xmlns:local="clr-namespace:ViewModels" />

<Application.Resources>
     <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <local:MainViewModel x:key="MainViewModel" />
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

//App.xaml.cs
MainViewModel mainViewModel = Current.ResourceDictionary["MainViewModel"];
mainViewModel.propertyInjection = new Dependency();

//MainView.xaml
<Window DataContext="{StaticResource MainViewModel}">

Оба способа являются допустимыми параметрами, и с небольшим управлением ключами можно смешивать и сопоставлятьиспользоваться в соответствии с требованиями.

2 голосов
/ 05 января 2011

Вы можете использовать первый подход к модели представления, в котором вы создаете экземпляры моделей представления (внедряя любые зависимости посредством внедрения в конструктор), а затем создаете экземпляр своего представления и устанавливаете его DataContext программно для экземпляра модели представления.

Я использую платформу Caliburn.Micro, которая автоматически просматривает местоположение и привязку через соглашения.Вы можете найти его на http://caliburnmicro.codeplex.com/

Оригинальный доклад Роба Айзенбурга «Построй свой собственный MVVM Framework» дает отличный обзор того, что стало Caliburn.Micro - http://live.visitmix.com/MIX10/Sessions/EX15

1 голос
/ 05 января 2011

Мне нравится использовать DataTemplate, определенный в словаре ресурсов в App.xaml (или в другом месте), чтобы отобразить ViewModel в View следующим образом:

<DataTemplate DataType="{x:Type vm:CustomerViewModel}">
    <vw:CustomerView />
</DataTemplate>

В результате автоматически назначается ViewModel в качестве DataContext представления во время выполнения. В этом случае я бы создал экземпляр объекта с именем, скажем, myCustomerViewModel, в ViewModel для окна или другого пользовательского элемента управления, в котором будет размещен CustomerView, а затем в представлении для этого окна использовал ContentControl следующим образом:

<ContentControl Content="{Binding Path=myCustomerViewModel}" />
0 голосов
/ 28 октября 2015

Полагаю, у вас есть зависимость, которую вы хотите использовать для конструктора, например:

class MainViewModel
{
    public interface IDependency { };
    readonly IDependency _dep;
    public MainViewModel (IDependency dep)
    {
        if (dep == null)
            throw new ArgumentNullException("IDependency dep cannot be null");
        _dep = dep;
    }
}
  1. Это то, что вы пытаетесь сделать ??

Во-вторыхНасколько я понимаю, чтобы иметь возможность использовать MainViewModel в XAML, вам нужно предоставить конструктор по умолчанию, который в сочетании с внедренной зависимостью представляет собой «Bastard Injection»: Какова реальная разница между «Bastard Injection» и«Инъекция бедного человека»

До сих пор я не видел способа избежать «Инъекции ублюдка» и все же смог бы это сделать:

<Window.DataContext>
    <local:MainViewModel />
</Window.DataContext> 

или что:

<UserControl.Resources>
    <DataTemplate DataType="{x:Type vm:ProgrammingViewModel}">
        <local:ProgrammingView />
    </DataTemplate>
</UserControl.Resources>
0 голосов
/ 05 января 2011

Я создаю модель представления для всего приложения и либо делаю ее контекстом данных моего главного окна, либо (если у меня не будет только одного главного окна) вставляю ее в словарь ресурсов приложения.Весь код запуска идет внутри конструктора модели представления приложения, и AVM представляет другие модели представления как свойства, чтобы к ним можно было получить доступ через привязку.

Это своего рода тупой инструмент, но он обладает достоинствомпростоты.

...