Чи є хороша формальна схема управління державою в MVVM?


21

Я почав дізнаватися про Redux та React у веб-світі, і чим більше я дізнаюсь про це, тим більше я розумію, наскільки болісне управління державою у настільному світі за допомогою архітектури MVVM у стилі WPF (використовуючи Caliburn спеціально для зв’язування поглядів до ViewModels).

Redux має кілька простих принципів, які диктують, яким чином слід керувати державою, роблячи оновлення інтерфейсу користувача, обробку подій та зміни стану набагато передбачуванішими. Принципи:

  • Єдине джерело істини (всі зміни, що змінюються, зберігаються в одному спільному об'єкті).
  • Держава доступна лише для читання. Він не може бути змінений компонентами через код, що зазвичай відбувається у WPF.
  • Стан можна змінювати лише за допомогою чистих функцій.

Архітектура MVVM WPF дозволяє вам створювати інтерактивні погляди дуже швидко, але проблеми налагодження, коли різні моделі перегляду та події змінюють стан, є кошмаром. Наприклад: запускається подія, яка змінила подання та спробувала встановити вкладку за замовчуванням, але дані не закінчили завантажуватися асинхронно з веб-служби, тому вкладка не існує (поки що), тому нічого не відбувається

Я витратив години на малювання діаграм, щоб спробувати і зрозуміти складні взаємодії між взаємопов'язаними компонентами viewModels, які оновлюють один одного.

Я розумію, що Redux має на меті вирішити частину цієї непередбачуваності. Чи є щось подібне чи архітектурний зразок, який би добре поєднувався з WPF, щоб допомогти краще керувати державою? Я не впевнений, наскільки добре працюватимуть принципи Redux в .NET, оскільки я ще їх не пробував. Можливо, у когось є досвід, який може дати поради?


У нас у браузері подібні проблеми. Прямий Javascript запуститься так рано, і DOM ще не побудований, тому не можна знайти жодних елементів інтерфейсу. На щастя, існує низка подій, які ми можемо використовувати для запуску затримки виконання якогось сценарію, поки інші речі не будуть далі. (Наприклад, DOMContentLoaded.)
Ерік Ейдт

1
Стан у скороченні фактично оновлюється, ніколи не змінюється.
Енді

1
Я знаю, що я спізнююся на вечірку, але є проект під назвою React.NET, який приносить архітектуру Redux до .NET.
SiberianGuy

Для тих, хто любить підхід ngrx / store у Angular проектах, є NetRx.Store - управління державою для .Net проектів, натхнене ngrx / store. Ви також можете знайти його в Nuget . Також є хороший зразок використання NetRx.Store з малюнком MVVM у проекті WPF
Віталій Ільченко

Відповіді:


8

Я думаю, я знаю, що ти маєш на увазі. В основному ви вирішуєте проблему, додаючи або "контролер", або "головний" модуль перегляду (виправданий псудокод)

тобто

public class MasterVM
{
    public ChildVM View1 {get;set;}
    public ChildVM View2 {get;set;}

    private Data data;
    public MasterVM()
    {
        View1.OnEvent += updateData;
    }

    private Action<int> updateData(int value)
    {
         View2.Value = value;
    }
}

коли ви робите це за допомогою шаблону посередника, я вважаю клас контролером. тобто.

public class Controller
{
    public Controller(MediatorService m)
    {
        m.Subscribe("valueupdated", updateData);
    }

    private Action<int> updateData(int value)
    {
         m.Publish("showvalue", value);
    }
}

public class View2
{
    public View2(MediatorService m)
    {
        m.Subscribe("showvalue", (int v)=> {Value = v;});
    }
}

Такі речі дозволяють розмістити свою "логіку потоку" або Оркестрацію подій у цих класах високого рівня та зберегти світловий код коду VM. Якщо ви хочете змінити ", коли користувач натискає КУПИТИ, замовлення обробляється" види речей, які ви знаєте, шукати у "OrderFlowController" або "OrderProcessVM" або як би ви хочете їх назвати. Замість комбінації BasketVM, PaymentVM, 3dSecureVM тощо тощо

Отже, у вашому конкретному прикладі "вкладка ще не готова" ви могли мати

public class Controller
{
    bool dataLoadCompleted;
    public Controller(MediatorService m)
    {
        m.Subscribe("setTabRequest", setTab); //message from view model with set tab button
        m.Subscribe("dataLoadComplete", dataLoadComplete); //message from data loading view model or some other controller?
    }

    private Action<int> setTab(int value)
    {
         if(!dataLoadCompleted)
         {
             m.Publish("error", "Please wait for data to load"); //message for error alert view model
         }
         else
         {
             m.Publish("setDefaultTab", value); //message for tab viewmodel
         }
    }

    private Action dataLoadComplete()
    {
         //persist state;
         dataLoadCompleted = true;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.