5

Привет всем.

Решил измотать себя, при помощи WPF. Ну и конечно, паттерн MVVM :)

Разумеется, сразу же столкнулся с проблемой, как при помощи MVVM паттерна открыть UserControl?

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

  • Что значит "открыть контрол"? – Алексей Саровский Jun 04 '15 at 18:37
  • @Алексей Саровский Да наверное, правильнее было описать принцип программы.

    Запускается программа. Открывается форма на которой размещен UserControl например Приветствия и описания программы.

    потом пользователь жмет кнопку далее и открывается следующий userControl скажем с формой регистрации и.т.д . При этом разумеется контрол с приветствием закрывается

    – Геннадий Писарев Jun 04 '15 at 18:46
  • Все, понял Вас. Хм... это как-то не очень православно, по-моему, на одной форме менять UserControl-ы. Разве что разместить на форме все UserControl, поставить Visible в false у нужных и этот Visible привязать к ViewModel. В нем уже выставлять Visible в true/false как нужно - но костыль жесткий слишком. А можно узнать, почему 1 форма именно? – Алексей Саровский Jun 04 '15 at 18:53
  • Даже сам не знаю :). Я Писал программки на WInForm. Так мне лень было каждый раз, создавать новую форму. Делать для нее настройки и все такое . А так Есть одна Форма, можно сказать дезаин программы один, просто подстовляешь новые контролы и все пучком.

    Честно сказать я совсем слаб в программировании. Мне это просто интересно я самоучка. несмотря на то что я написал программу для моего знакомого. У которого есть свой биллиард бар. так я дал ему программу которая считала сколько времени его клиент играл за

    столом и на какую сумму деллал заказы

    – Геннадий Писарев Jun 04 '15 at 19:08
  • Если можете, то подскажите как правильно. – Геннадий Писарев Jun 04 '15 at 19:09
  • Маленькая поправка. я не лепил контролы на одну форуму. по принципу visible.

    я их добавляв в нужный момент. this.Controls.Add(сам контрол);

    по этому не было большой путаницы

    – Геннадий Писарев Jun 04 '15 at 19:23
  • Ну правильного ничего в мире нет... Но я бы все-таки лепил отдельные формы. С ними же мучиться совсем не нужно - почитайте про IoC-контейнеры (LightInject, например) и сразу куча проблем, которые возникают при многооконном приложении, отпадает. Просто если так как Вы делать - слишком много ответственности у классов и слишком много кода, наверно. – Алексей Саровский Jun 04 '15 at 19:45

1 Answers1

6

Популярный путь такой.

Вы прописываете

class MainVM : INotifyPropertyChanged
{
    VM activePageVM;
    public VM ActivePageVM
    {
        get { return activePageVM; }
        set { activePageVM = value; NotifyPropertyChanged(); }
    }

    // обвеска для INotifyPropertyChanged
}

обычным образом. Теперь, ваше окно выглядит так:

<Window ...>
    <ContentPresenter Content="{Binding ACtivePageVM}"/>
</Window>

(можете ещё вокруг добавить общую обвеску, нужную на всех страницах).

Осталось только сделать так, чтобы ваш ContentPresenter выбирал правильный UserControl в зависимости от типа VM. Это делается очевидной диспетчеризацией через DataTemplate:

<DataTemplate DataType="{x:Type vm:FirstVM}">
    <ui:FirstUserControl/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:SecondVM}">
    <ui:SecondUserControl/>
</DataTemplate>

Эту диспетчеризацию поместите в App.xaml или куда-то ещё, где она видна в главном окне. Если вам надо где-то локально перекрыть отображение для какого-то типа, пользуйтесь локальными ресурсами, они всегда имеют приоритет.

VladD
  • 206,799
  • @VlalD Спасибо за ответ. Все вроде понятно. Только у меня выдает ошибку NotifyPropertyChanged(); – Геннадий Писарев Jun 05 '15 at 09:08
  • Ну, это ж набросок кода. Вам, понятно, нужно реализовать стандартным образом INotifyPropertyChanged. У вас ещё на многоточие в Window будет ругаться. И для DataTemplate'ов вам нужно будет указать пространства имён vm и ui. – VladD Jun 05 '15 at 09:25
  • @VlaID Естественно я добавил, пространство имен. Иначе на меня ругался бы еще и интерфейс INotifyPropertyChanged – Геннадий Писарев Jun 05 '15 at 09:49
  • @ГеннадийПисарев: Посмотрите, как заимплементировано, например, здесь (класс DemoCustomer). – VladD Jun 05 '15 at 09:52