2010-07-27 26 views
10

Tôi đang cố gắng tìm ra cách để ViewModel xử lý việc lưu hoặc khôi phục trạng thái của trang khi trang được điều hướng Từ hoặc Tới. Điều đầu tiên tôi đã thử là thêm một hành vi EventToCommand vào trang, nhưng các sự kiện (OnNavigatedFrom và OnNavigatedTo) được khai báo được bảo vệ và EventToCommand không thấy các sự kiện liên kết với.Xử lý các sự kiện OnNavigatedFrom/OnNavigatedTo trong ViewModel

Tiếp theo, tôi nghĩ tôi sẽ cố gắng sử dụng các lớp Messenger để vượt qua một thông điệp tới các ViewModel sử dụng mã vào những năm Xem mã sau:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) 
{ 
    Messenger.Default.Send<PhoneApplicationPage>(this); 
    base.OnNavigatedFrom(e); 
} 

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
    Messenger.Default.Send<PhoneApplicationPage>(this); 
    base.OnNavigatedTo(e); 
} 

Nhưng điều này dường như có hai vấn đề, đầu tiên là có mã này trong mã đằng sau trang. Thứ hai, ViewModel không thể cho biết sự khác biệt giữa các sự kiện OnNavigatedFrom và OnNavigatedTo mà không cần phải tạo một tập hợp các lớp bao bọc cho đối tượng PhoneApplicationPage (xem UPDATE bên dưới).

Cách thân thiện nhất với MVVM-Light để xử lý những sự kiện này là gì?

UPDATE: tôi đã có thể giải quyết vấn đề thứ hai bằng cách gửi tin nhắn như thế này:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) 
{ 
    Messenger.Default.Send<PhoneApplicationPage>(this,"NavigatedFrom"); 
    base.OnNavigatedFrom(e); 
} 

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
    Messenger.Default.Send<PhoneApplicationPage>(this, "NavigatedTo"); 
    base.OnNavigatedTo(e); 
} 

và Đăng ký chúng như thế này:

Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedFrom", false, (action) => SaveState(action)); 
Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedTo", false, (action) => RestoreState(action)); 

Trả lời

1

Hình như bạn có một giải pháp cho bạn vấn đề rồi. Tôi cũng xin đề nghị như sau:

Nhìn vào bằng một trong những giá trị tin được cung cấp trong MVVM-toolkit, chẳng hạn như:

NotificationMessage<T> 

Như thế này:

Messenger.Default.Send<NotificationMessage<PhoneApplicationPage>>(
new NotificationMessage<PhoneApplicationPage>(this, "Message")); 
5

Thực thi một lệnh từ mã phía sau là sạch hơn nhiều so với thông qua toàn bộ tin nhắn mess. Sau khi tất cả không có gì sai với quan điểm biết về DataContext của nó.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e); 
     viewModel.NavigatedToCommand.Execute(e.Uri); 
    } 

    ProfileViewModel viewModel 
    { 
     get 
     { 
      return this.DataContext as ProfileViewModel; 
     } 
    } 

Cập nhật: Đi qua trong NavigationContext.QueryString có lẽ hữu ích hơn, vì nó đã phân tích các tham số và giá trị.

+0

Không phù hợp với MVVM Light. Tôi chỉ nghĩ về thời gian thực hiện. Chuyển từ VIEW sang ViewModel thông qua ViewModelLocator –

0

Tôi nghĩ những gì Ryan đã nhận được, là một thực tế rằng bạn đang sử dụng PhoneApplicationPage như tin nhắn đang được gửi, thay vì một tin nhắn thực tế.

Bạn đang làm điều này:

Messenger.Default.Send<PhoneApplicationPage>(this); 

mà đang gửi một thông điệp của loại PhoneApplicationPage. Có thể bạn không cần gửi toàn bộ PhoneApplicationPage làm tin nhắn.

Bạn có thể tạo một số thư cho NavigatingTo/NavigatingFrom, tức là.

Messenger.Default.Send<NavigatingToMessage>(new NavigatingToMessage()); 

, vv

tôi chắc chắn rằng có một triệu cách tốt hơn để làm điều này, tôi chỉ đi cùng với cách bạn đã đặt mọi thứ lên.Cá nhân, lớp ViewModelBase của tôi có các phương thức NavigatingTo/NavigatingFrom và tôi ghi đè các phương thức tương ứng trong View và gửi chúng tới ViewModel của tôi.

3

Xin lỗi vì đã trễ ba năm cho câu hỏi này. Có, tôi vẫn đang sử dụng Silverlight. Được rồi tôi muốn viết nó trong Page code-behind như thế này:

// Executes when the user navigates to this page. 
protected override void OnNavigatedTo(NavigationEventArgs e) 
{ 
    this.HandleOnNavigatedTo(e); 
} 

Tôi đang sử dụng một phương pháp mở rộng như thế này:

phương pháp
public static void HandleOnNavigatedTo(this Page page, NavigationEventArgs e) 
{ 
    var vm = page.DataContext as IPageNavigationViewModel; 
    if (vm == null) return; 
    vm.HandleOnNavigatedTo(e); 
} 

Phần mở rộng ngụ ý rằng Page phải có một Xem các mẫu mà triển khai IPageNavigationViewModel trong DataContext. Đối với tôi, đây là sự thỏa hiệp phân tách mối quan tâm nơi Trang chỉ biết về các loại dữ liệu có mục đích chung nhất trong Miền. Đây giao diện:

using System.Windows.Navigation; 

namespace Fox.Silverlight.ViewModels 
{ 
    /// <summary> 
    /// Defines View Model members for frame-navigation pages. 
    /// </summary> 
    public interface IPageNavigationViewModel 
    { 
     /// <summary> 
     /// Handles the <see cref="Page.OnNavigatedTo"/> method in the View Model. 
     /// </summary> 
     /// <param name="e">The <see cref="NavigationEventArgs"/> instance containing the event data.</param> 
     void HandleOnNavigatedTo(NavigationEventArgs e); 

     /// <summary> 
     /// Handles the <see cref="Page.OnNavigatedFrom"/> method in the View Model. 
     /// </summary> 
     /// <param name="e">The <see cref="NavigationEventArgs"/> instance containing the event data.</param> 
     void HandleOnNavigatedFrom(NavigationEventArgs e); 
    } 
} 
+0

btw: Tôi là người dùng MVVM Light trong thời gian dài ... – rasx

0

tôi thực hiện một mẫu bằng cách sử dụng câu trả lời được cập nhật bên trong câu hỏi:

MainViewModel.xaml.cs:

public class MainViewModel : ViewModelBase 
{ 
    public MainViewModel() 
    { 
     Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedTo", false, ExecuteNavigatedTo); 
    } 

    // action contains everything you want. 
    private void ExecuteNavigatedTo(Page page) 
    { 
     // example 
     bool b = page.NavigationContext.QueryString.ContainsKey("id"); 
    } 
} 

MainViewModel.xaml.cs:

protected override void OnNavigatedTo(NavigationEventArgs e) 
{ 
    Messenger.Default.Send<PhoneApplicationPage>(this, "NavigatedTo"); 
    base.OnNavigatedTo(e); 
} 
Các vấn đề liên quan