Как загрузить пользовательский контроль wpf в шаблоне MVVM - PullRequest
6 голосов
/ 20 мая 2010

Я создаю пользовательский элемент управления wpf, который находится в шаблоне mvvm. Итак, у нас есть: view (без кода в файле codebehind), viewmodel, model, dataaccess files.

У меня есть MainWindow .xaml в качестве файла представления, который мне нужно связать с MainWindowModel .cs.

Обычно в приложении wpf это можно сделать с помощью события onStartUp в файле App.xaml. Но в пользовательском контроле, так как у нас нет App.xaml ... Как мне этого добиться?

Пожалуйста, помогите: (... Заранее спасибо !!!

Ответы [ 6 ]

16 голосов
/ 20 мая 2010

Вы можете использовать ContentControl с DataTemplate для привязки UserControl (View) к ViewModel:

<DataTemplate DataType="{x:Type vm:MyViewModel}">
    <v:MyUserControl />
</DataTemplate>

...

<ContentControl Content="{Binding Current}" />

WPF автоматически выберет DataTemplate в зависимости от типа Content

5 голосов
/ 06 октября 2011

Я знаю, что это старый вопрос с ответом, но у меня другой подход. Мне нравится делать неявные отношения в файле App.xaml:

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
        <Views:KioskView />
    </DataTemplate>
</Application.Resources>

При этом нет необходимости устанавливать DataContext в любом месте.

ОБНОВЛЕНИЕ >>>

В ответ на запрос @Vignesh Natraj, вот более полное объяснение:

После того, как вы настроили DataTemplate в элементе Resources, вы можете отобразить KioskView в этом примере, добавив экземпляр KioskViewModel в любом месте вашего XAML. Это может быть заполнение MainWindow или только внутри определенного раздела экрана. Вы также можете разместить несколько экземпляров KioskViewModel в ListBox, и он будет генерировать несколько экземпляров KioskView.

Вы можете добавить экземпляр KioskViewModel в свой XAML несколькими способами, в зависимости от ваших требований. Один из способов - объявить пространство имен XML для проекта, содержащего файл KioskViewModel.cs, и просто добавить его экземпляр в ContentControl на страницу, где вы хотите, чтобы ваше представление отображалось. Например, если у вас есть UserControl с именем MainView, а файл KioskViewModel.cs находится в пространстве имен Kiosk.ViewModels, вы можете использовать базовый XAML, например:

<UserControl x:Class="Kiosk.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="clr-namespace:Kiosk.ViewModels">
    <UserControl.Resources>
        <ViewModels:KioskViewModel x:Key="KioskViewModel" />
        <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
            <Views:KioskView />
        </DataTemplate>
    </UserControl.Resources>
    <ContentControl Content="{StaticResource KioskViewModel}" />
</UserControl>

Я предпочитаю использовать шаблон проектирования MVVM с WPF, поэтому у меня будет класс модели базового вида, обеспечивающий полезные функции, такие как реализация необходимого интерфейса INotifyPropertyChanged. Затем у меня есть свойство с именем ViewModel в модели основного (верхнего уровня) вида BaseViewModel. Это дает мне хороший способ изменить свойство ViewModel на любую модель представления, основанную на BaseViewModel, и, следовательно, иметь возможность изменять связанный вид из модели представления.

Например, в классе MainViewModel.cs, связанном с MainView, есть поле и соответствующее свойство:

private BaseViewModel viewModel = new KioskViewModel();
public BaseViewModel ViewModel
{
    get { return viewModel; }
    set { viewModel = value; NotifyPropertyChanged("ViewModel"); }
}

Как видите, он запускается как экземпляр KioskViewModel, но может быть изменен на любое другое представление в любое время в ответ на взаимодействие с пользователем. Для этой настройки XAML очень похож, но вместо объявления экземпляра модели представления в элементе Resources мы связываемся со свойством в MainViewModel:

<UserControl x:Class="Kiosk.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="clr-namespace:Kiosk.ViewModels">
    <ContentControl Content="{Binding ViewModel}" />
</UserControl>

Обратите внимание, что для этого примера нам нужно объявить два (или больше, чтобы сделать этот подход полезным) DataTemplate s в файле App.xaml:

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
        <Views:MainView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}">
        <Views:KioskView />
    </DataTemplate>
</Application.Resources>
2 голосов
/ 20 мая 2010

Есть бесконечные способы сделать это, все они попадают в одну из двух категорий: «сначала посмотреть» или «сначала модель».

В режиме «представление сначала» сначала создается представление (например, ваше основное окно), а затем (например, в коде сзади) представление создает экземпляр ViewModel и устанавливает его как его текстовый текст):

private void WindowLoaded(object sender, EventArgs args)
{
   this.DataContext = ViewModelService.GetViewModelX();
}

В режиме «сначала модель» сначала появляется ViewModel, а затем создается представление.

// method of the viewmodel 
public void LoadView()
{
     // in this example the view abstracted using an interface
     this.View = ViewService.GetViewX();
     this.View.SetDataContext(this);
     this.View.Show();    
}

Примеры, приведенные здесь, являются лишь одним из многих. Вы можете посмотреть на различные MVVM-фреймворки и посмотреть, как они это делают.

2 голосов
/ 20 мая 2010

Я использую MVVM Light Toolkit , который имеет класс ViewModelLocator, в который можно помещать свойства для моделей представления. Затем вы создаете ссылку на ViewModelLocator в вашем Mainwindow.xaml следующим образом:

<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True"/>

На панели сетки, или что вы используете, вы можете установить текст данных следующим образом:

<Grid DataContext="{Binding MainWindowViewModel, Source={StaticResource Locator}}">
...
</Grid>

Вы также можете использовать MEFedMVVM , который потенциально добавляет немного большей гибкости с точки зрения возможности обмена различными реализациями viewModel в представлении.

Гибкость обеих этих библиотек заключается в том, что вам не нужно использовать их базовые классы ViewModel, если вы этого не хотите - ViewModelLocator и MEFedMVVM могут работать с любым классом.

0 голосов
/ 18 февраля 2015

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

0 голосов
/ 21 мая 2010

Мы можем использовать ObjectDataProvider для вызова метода внутри объекта .. как следует:

<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
                    MethodName="ConvertTemp" 
                    x:Key="convertTemp">

Есть ли возможность сделать то же самое с помощью DataTemplate

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...