Счупен ли е шаблонът MVVM?

Имам WPF-приложение, базирано на MVVM-образец. Всичко работи добре. В бизнес логиката на View-Model трябва да извикам някои диалогови прозорци. Внедрих го чрез интерфейс (реализацията на интерфейса е в слой View).
За диалоговите прозорци трябва да задам родителския прозорец, така че функцията в интерфейса има аргумент "parentView".

В моя ViewModel имам свойство „Изглед“ от тип „обект“ за родителски прозорец. Това свойство поставям като аргумент за инстанциране на диалог.

Тъй като свойството "View" е от тип "object" и се задава от слоя View и се препраща обратно към слоя View, слоят View-Model няма зависимости от слоя View.

Какво мислите, нарушил ли съм MVVM-шаблона?


person Rekshino    schedule 21.03.2017    source източник


Отговори (2)


Какво мислите, нарушил ли съм MVVM-шаблона?

Не. Моделът на изгледа не зависи от изгледа, той знае само за интерфейс, на който лесно бихте могли да се подиграете във вашите модулни тестове. Така че това всъщност не нарушава модела, стига "Изглед" да е просто абстракция на нещо.

От съображения за безопасност на типа вероятно трябва да помислите за промяна на типа на параметъра от object на строго типизиран тип интерфейс.

person mm8    schedule 21.03.2017
comment
Благодарим ви за намека относно безопасността на типа. Наистина ще помисля. - person Rekshino; 22.03.2017
comment
Зависимостите между типове са подробности на ниво клас (ниско ниво по отношение на архитектурата). При дизайн на компонент на приложения от високо ниво (единствената грижа на MVVM) моделът е нарушен. По отношение на MVVM единствената грижа на компонента на модела на изгледа е да представи компонента на модела (бизнес логика/домейн) на компонента на изгледа, действащ като интерфейс, въведен за отделяне на двата компонента. - person BionicCode; 26.09.2020
comment
Тъй като класическото приложение се използва от човек, класическото приложение отразява потребителски истории или случаи на употреба, които имат цел. Тези случаи на употреба създават входни данни, които се обработват от бизнес логиката. Бизнес логиката връща резултат, който е целта на потребителското взаимодействие и всъщност се показва на потребителя. Единствената цел на бизнес логиката е да служи на потребителските истории. Когато е правилно проектиран, тогава компонентът на модела на изглед не трябва да стартира такава операция като показване на диалогов прозорец за взаимодействие с потребителя. - person BionicCode; 26.09.2020
comment
При проектирането на приложението моделът на изгледа не е потребител и няма потребителска история: той никога не би активно поискал или изчакал въвеждане от потребителя или задействал бизнес логиката за собствените си интереси (той няма интереси тъй като е пасивен презентатор/архитектурен интерфейс). Замяната на Window с IWindow или IDialogService се нарича Инверсия на зависимостта (модел или принцип на ниво клас, напр. за разрешаване на подигравка в тестове на единици) и няма нищо общо с MVVM (модел на ниво компонент за отделяне на компоненти/отговорности). - person BionicCode; 26.09.2020

Без приятел - това е решен проблем. Искам да кажа, че няма истинска красота във всички решения, но можете да използвате Dialog-Service например.

Наистина лесно внедряване на това би било Singleton, което има статично поле с вашия Main-Window. Вече можете да извиквате вашите диалози от този клас.

Всъщност мисля, че например MahApps върви така, но те го регистрират по фантастичния начин:

<controls:MetroWindow 
        x:Class="SomeMetroWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
        Dialog:DialogParticipation.Register="{Binding}"> <!-- watch this pls --->
<!-- ... --->
</controls:MetroWindow>

Ето един пример за общо изпълнение. А ето още една статия за статии по тази тема.

Както казах - не много красиво, но решено.

person Peter    schedule 21.03.2017
comment
Здравей Питър, благодаря ти за отговора. Всъщност работи при мен с моя вариант на диалогова услуга (по-малко код, повече гъвкавост). За мен поставянето на родителя на единичния родител не е решение (понякога има различни родители). - person Rekshino; 22.03.2017
comment
Като цяло не бих препоръчал WPF да пишете свой собствен DialogService, защото взимате Framework, който разполага с това най-много време. Докато в Windows-Store-Apps вече има собствени решения. - person Peter; 22.03.2017