2009-05-22 5 views
11

Trong các dự án trước đây của tôi, tôi đã triển khai hệ thống hoàn tác trong C++ và tôi biết nó hoạt động như thế nào. Tôi cũng biết về mẫu Command.Hoàn tác bên trong WPF M-V-VM, nó phù hợp như thế nào?

Tôi sẽ triển khai một ứng dụng máy tính để bàn C#/WPF và muốn căn cứ thiết kế của tôi trên mẫu M-V-VM.

Ứng dụng này sẽ:

  • được tương đối một dự án nhỏ (2-3 tuần ước tính làm việc cho 1 dev)
  • có một mô hình dữ liệu đơn giản với sự bền bỉ (LINQ to XML)
  • hỗ trợ lùi/redo

Tôi đã tự hỏi liệu có ai có kinh nghiệm triển khai hệ thống hoàn tác khi theo mẫu MV-VM không. Làm thế nào nó sẽ phù hợp với nó? Làm thế nào nó có thể được hưởng lợi từ các thông báo INotifyPropertyChanged và INotifyCollectionChanged vì vậy công việc tối thiểu là cần thiết khi thực hiện các Mô hình (đối tượng kinh doanh).

Tôi nghĩ hệ thống hoàn tác sẽ được tích hợp vào lớp ViewModel vì nó là trạng thái giao diện người dùng.

Bạn nghĩ gì?

Trả lời

12

Dưới đây là giải pháp tôi sử dụng cho dự án của tôi. Giải pháp được chứng minh là hoạt động hoàn hảo.

Hệ thống đang sử dụng các đối tượng sự kiện hoàn tác, trong đó mỗi sự kiện hoàn tác biết cách hoàn tác và làm lại chính nó.

interface IUndoEvent 
{ 
    void Undo(); 
    void Redo(); 
} 

Tôi có thể xây dựng hệ thống bằng cách chỉ triển khai 2 sự kiện hoàn tác: Một cho thay đổi thuộc tính; một để thay đổi bộ sưu tập.

Ý tưởng là những sự kiện đó triển khai Hoàn tác/Làm lại bằng cách sửa đổi mô hình trực tiếp.

class PropertyChangeUndoEvent : IUndoEvent 
{ 
    private ModelBase _target; 
    private string _propertyName; 
    private object _oldValue; 
    private object _newValue; 

    public PropertyChangeUndoEvent(ModelBase target, string propertyName, object oldValue, object newValue) 
    { 
     _target = target; 
     _propertyName = propertyName; 
     _oldValue = oldValue; 
     _newValue = newValue; 
    } 

    public void Undo() 
    { 
     SetValue(_oldValue); 
    } 

    public void Redo() 
    { 
     SetValue(_newValue); 
    } 

    private void SetValue(object value) 
    { 
     // Set Value on the _target using reflection (_propertyName) 
    } 
} 

ViewModel chăm sóc tạo undo các sự kiện bằng cách gọi chức năng ViewModelBase:

class MyViewModel : ViewModelBase 
{ 
    public string Name 
    { 
     get { return _model.Name; } 

     // The SetValue will create a undo event, and push it to the UndoManager 
     set { SetValue(_model, "Name", value); } 
    } 
} 

Cuối cùng, có một UndoManager (dự án singleton) mà các cửa hàng đống undo và redo stack.

1

Tôi cho rằng bạn đang ghép mẫu Command với một vật lưu niệm?

Tôi nghĩ hệ thống hoàn tác sẽ được tích hợp vào lớp ViewModel vì nó là trạng thái giao diện người dùng.

?! Thông thường, hoàn tác/làm lại các hành động trên các đối tượng kinh doanh và giao diện người dùng phản ánh lớp doanh nghiệp.

Giả sử chúng tôi có một Lớp sản phẩm có chuỗi "Mô tả". ProductVM cho thấy một thuộc tính chuỗi làm tăng PropertyChanged. Khi sửa đổi, bộ nhớ lưu giữ mẫu kiểu cũ. Nếu bạn hoàn tác, hãy khôi phục bộ lưu trữ bằng cách sử dụng ProductVM.Description = (memento as Product) .Mô tả: mô hình sẽ được cập nhật và giao diện người dùng.

NB: tránh (vật lưu niệm như sản phẩm), chỉ dành riêng cho mẫu;)

3

Bạn có thể thấy Khung hoàn tác được giám sát hữu ích. http://muf.codeplex.com/. Nó không sử dụng mẫu lệnh "trên xuống", mà thay vào đó theo dõi các thay đổi khi chúng xảy ra và cho phép bạn đặt một đại biểu trên ngăn xếp hoàn tác sẽ đảo ngược thay đổi.

Tôi đã tạo điều này như một phần của ứng dụng WPF được xây dựng bằng MVVM. Hầu hết các hành động hoàn tác có nguồn gốc trong mô hình miền cơ bản của chúng tôi, nhưng chúng tôi cũng nối vào một số khu vực của ViewModels để cho phép hoàn tác/làm lại ở đó.

Bạn có thể tìm thêm thông tin và tài liệu trên trang web codeplex tại http://muf.codeplex.com/.