Có một mô hình chính thức tốt để quản lý trạng thái trong MVVM không?


21

Tôi đã bắt đầu tìm hiểu về Redux và React trong thế giới web và càng tìm hiểu về nó, tôi càng nhận ra việc quản lý trạng thái đau đớn như thế nào trong thế giới máy tính để bàn với kiến ​​trúc kiểu MVVM của WPF (đặc biệt sử dụng Caliburn để ràng buộc Lượt xem để ViewModels).

Redux có một vài nguyên tắc đơn giản chỉ ra cách quản lý trạng thái, thực hiện cập nhật giao diện người dùng, xử lý sự kiện và thay đổi trạng thái dễ dự đoán hơn nhiều. Các nguyên tắc là:

  • Một nguồn sự thật duy nhất (tất cả trạng thái có thể thay đổi được lưu trữ trong một đối tượng chia sẻ duy nhất).
  • Nhà nước là chỉ đọc. Nó không thể được sửa đổi bởi các thành phần thông qua mã, thường là những gì xảy ra trong WPF.
  • Nhà nước chỉ có thể được sửa đổi bởi các chức năng thuần túy.

Kiến trúc MVVM của WPF cho phép bạn xây dựng các khung nhìn tương tác rất nhanh, nhưng việc gỡ lỗi các vấn đề khi các chế độ xem và sự kiện khác nhau đều thay đổi trạng thái là một cơn ác mộng. Ví dụ: một sự kiện được kích hoạt đã thay đổi chế độ xem và cố gắng đặt tab mặc định, nhưng dữ liệu chưa tải xong không đồng bộ từ dịch vụ web để tab không tồn tại (chưa) nên không có gì xảy ra

Tôi đã dành hàng giờ để vẽ sơ đồ để thử và hiểu các tương tác phức tạp giữa các thành phần viewModels liên quan đến nhau cập nhật lẫn nhau.

Tôi hiểu rằng Redux nhằm mục đích giải quyết một số tình trạng khó lường này. Có một cái gì đó tương tự, hoặc một mô hình kiến ​​trúc sẽ phù hợp với WPF để giúp quản lý trạng thái tốt hơn? Tôi không chắc các nguyên tắc Redux sẽ hoạt động tốt như thế nào trong .NET vì tôi chưa thử chúng. Có lẽ ai đó có một số kinh nghiệm có thể đưa ra một số lời khuyên?


Chúng tôi có một loại vấn đề tương tự trong trình duyệt. Javascript đơn giản sẽ chạy rất sớm và DOM chưa được xây dựng, vì vậy người ta không thể tìm thấy bất kỳ thành phần UI nào. May mắn thay, có một số Sự kiện, chúng ta có thể sử dụng để kích hoạt việc thực thi một số tập lệnh bị trì hoãn cho đến khi những thứ khác đi xa hơn. (Chẳng hạn như DOMContentLoaded.)
Erik Eidt

1
Trạng thái trong redux thực sự được cập nhật, không bao giờ sửa đổi.
Andy

1
Tôi biết tôi đến bữa tiệc muộn nhưng có một dự án có tên React.NET mang kiến ​​trúc Redux đến .NET.
SiberianGuy

Đối với những người thích cách tiếp cận của ngrx / store trong các dự án Angular, có NetRx.Store - quản lý nhà nước cho các dự án .Net, lấy cảm hứng từ ngrx / store. Bạn có thể tìm thấy nó tại Nuget là tốt. Ngoài ra, có một mẫu sử dụng NetRx.Store tốt với mẫu MVVM trong dự án WPF
Vitalii Ilchenko

Câu trả lời:


8

Tôi nghĩ tôi biết ý của bạn. Về cơ bản, bạn giải quyết vấn đề bằng cách thêm một chế độ xem 'trình điều khiển' hoặc 'chế độ chính' (xin lỗi psudocode)

I E

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;
    }
}

Khi bạn làm điều này với Mẫu Người hòa giải, tôi nghĩ về lớp với tư cách là Người kiểm soát. I E.

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;});
    }
}

Loại điều này cho phép bạn đặt 'luồng logic' hoặc Điều phối sự kiện trong các lớp bền vững ở mức độ cao này và giữ cho mã VM sáng. Nếu bạn muốn thay đổi 'khi người dùng nhấp vào MUA, đơn hàng được xử lý' loại điều bạn biết cần tìm trong 'OrderFlowContoder' hoặc 'OrderProcessVM' hoặc tuy nhiên bạn muốn đặt tên cho chúng. Thay vì kết hợp giữa BasketVM, PaymentVM, 3dSecureVM, v.v.

Vì vậy, trong ví dụ cụ thể của bạn về 'tab chưa sẵn sàng', bạn có thể có

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;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.