Câu hỏi WPF MVVM Cách đúng để kích hoạt sự kiện khi xem từ ViewModel


Trong ứng dụng WPF của tôi, tôi có 2 Windows (cả Windows đều có ViewModel riêng của họ):

  1. Cửa sổ chính của ứng dụng hiển thị danh sách với nhiều từ (ràng buộc với MainViewModel)

  2. Cửa sổ hộp thoại cho phép người dùng thêm các mục mới vào danh sách (ràng buộc với AddWordViewModel)

MainViewModel có Bài viết thuộc tính của Danh sách (bộ sưu tập này được điền bởi một trong các lớp dịch vụ) được liên kết với ListBox của Cửa sổ Chính

AddWordViewModel có SaveWordCommand bị ràng buộc với nút Save Add Dialog của hộp thoại. Nhiệm vụ của nó là lấy văn bản được nhập bởi người dùng và chuyển nó vào lớp dịch vụ.

Sau khi người dùng nhấp vào nút Lưu, tôi cần thông báo cho MainViewModel tải lại các bài viết từ dịch vụ.

Ý tưởng của tôi là để lộ lệnh công khai trong MainViewModel và thực hiện nó từ AddWordViewModel

Cách chính xác để thực hiện nó là gì?

Cảm ơn bạn!


20
2018-04-28 17:10


gốc




Các câu trả lời:


Event Aggregators là một cách khá tốt để giải quyết loại vấn đề này. Về cơ bản có một lớp tập trung (vì đơn giản vì chúng ta hãy nói đó là một Singleton và đối mặt với cơn thịnh nộ có thể có của những kẻ chống singleton) có trách nhiệm chuyển các sự kiện từ một đối tượng này sang đối tượng khác. Với tên lớp của bạn, việc sử dụng có thể trông giống như sau:

public class MainViewModel
{
    public MainViewModel()
    {
        WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>();
        event.Subscribe(WordAdded);
    }

    protected virtual void WordAdded(object sender WordAddedEventArgs e)
    {
        // handle event
    }
}

public class AddWordViewModel
{    
    //From the command
    public void ExecuteAddWord(string word)
    {
        WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>();
        event.Publish(this, new WordAddedEventArgs(word));
    }
}

Ưu điểm của mẫu này là bạn có thể dễ dàng mở rộng ứng dụng của mình để có nhiều cách tạo từ và nhiều Chế độ xem quan tâm đến các từ đã được thêm vào và không có sự kết hợp giữa hai từ để bạn có thể thêm và xóa chúng cần để.


Nếu bạn muốn tránh singleton (và cho mục đích thử nghiệm tôi sẽ đề nghị bạn làm) thì nó có thể là giá trị nhìn vào tiêm phụ thuộc, mặc dù đó thực sự là một vấn đề khác.


Được rồi, suy nghĩ cuối cùng. Tôi thấy từ đọc lại câu hỏi của bạn rằng bạn đã có một số loại lớp Dịch vụ Word xử lý việc truy xuất và lưu trữ các đối tượng Word. Không có lý do gì mà dịch vụ không thể chịu trách nhiệm nâng cao sự kiện khi từ mới được thêm vì cả hai ViewModels đã được ghép với nó. Mặc dù tôi vẫn đề nghị EventAggregator linh hoạt hơn và là giải pháp tốt hơn, nhưng YAGNI có thể áp dụng ở đây

public class WordService
{
    public event EventHandler<WordAddedEventArgs> WordAdded;

    public List<string> GetAllWords()
    {
        //return words
    }

    public void SaveWord(string word)
    {
        //Save word
        if (WordAdded != null) WordAdded(this, new WordAddedEventArgs(word));
        //Note that this way you lose the reference to where the word really came from
        //probably doesn't matter, but might
    }
}

public class MainViewModel
{
    public MainViewModel()
    {
        //Add eventhandler to the services WordAdded event
    }
}

Những gì bạn muốn tránh làm là giới thiệu sự ghép nối giữa các ViewModels mà bạn sẽ tạo ra bằng cách gọi một lệnh trên một ViewModel với nhau, điều này sẽ hạn chế các tùy chọn của bạn để mở rộng ứng dụng (nếu ViewModel thứ hai trở nên quan tâm đến các từ mới , bây giờ là trách nhiệm của AddWordViewModel để nói điều đó à?)


18
2018-04-28 17:42



Cảm ơn bạn cho câu trả lời rất chi tiết. Sẽ phải đào sâu vào nó :) Rất nhiều niềm vui sắp tới :) - Daniil Harik
Tôi đã đi đầy đủ OO với một đồ thị đối tượng lớn để thực hiện MVVM của tôi. 2 năm xuống dòng và làm thay đổi cấu trúc là khá khó khăn. Tôi ước tôi đã đi cho mô hình tổng hợp / hòa giải vì tính linh hoạt lớn. BEWARE: rò rỉ bộ nhớ. Đảm bảo rằng trình tổng hợp của bạn sử dụng các tham chiếu yếu. - Gusdor