2010-10-04 26 views
12

Tôi nút trong chế độ xem, được gắn với thuộc tính ICommand của ViewModel (thực ra là RelayCommand từ mvvv-light)Logic điều hướng ở đâu, Xem, Chế độ xemModel hoặc ở nơi khác?

Nếu người dùng nhấp vào nút tôi muốn điều hướng đến chế độ xem mới. Tất nhiên NavigationService là một phần của View chứ không phải ViewModel. Điều đó ngụ ý rằng điều hướng là trách nhiệm của Chế độ xem? Nhưng trong trường hợp của tôi, khung nhìn tôi sẽ xuất hiện khi nút được nhấp tùy thuộc vào nhiều yếu tố, bao gồm người dùng đã đăng nhập, trạng thái cơ sở dữ liệu, v.v. Chắc chắn View không cần tất cả thông tin đó.

Tùy chọn ưa thích để thực hiện cuộc gọi NavigationService.Navigate là gì?

Trả lời

12

Nếu bạn đã sử dụng MVVM Light, một tùy chọn là sử dụng bus thông báo mà nó bao gồm. Vì vậy, bạn liên kết nút của bạn với một RelayCommand trên mô hình xem, như bạn đã nói bạn đã làm. Trong trình xử lý cho RelayCommand của bạn, bạn có thể đưa ra quyết định về chế độ xem để điều hướng đến. Điều này giữ tất cả logic đó trong mô hình khung nhìn.

Khi trình xử lý lệnh của bạn đã quyết định xem điều hướng nào, nó có thể xuất bản một tin nhắn trên xe buýt tin nhắn. Chế độ xem của bạn sẽ lắng nghe thông điệp đó và sau đó sử dụng NavigationService để thực sự thực hiện điều hướng. Vì vậy, nó không làm bất cứ điều gì khác hơn là chờ đợi để được thông báo để điều hướng một nơi nào đó và sau đó điều hướng nơi nó được nói.

Tôi đã làm điều này bằng cách xác định lớp NavigationMessage mà các kiểu xem của tôi có thể xuất bản và lớp cơ sở chế độ xem mà lượt xem của tôi kế thừa từ đó chứa trình nghe. NavigationMessage trông giống như sau:

public class NavigationMessage : NotificationMessage 
{ 
    public string PageName 
    { 
     get { return base.Notification; } 
    } 

    public Dictionary<string, string> QueryStringParams { get; private set; } 

    public NavigationMessage(string pageName) : base(pageName) { } 

    public NavigationMessage(string pageName, Dictionary<string, string> queryStringParams) : this(pageName) 
    { 
     QueryStringParams = queryStringParams; 
    } 
} 

Điều này cho phép chỉ cần chuyển tên trang hoặc tùy chọn cũng bao gồm bất kỳ tham số chuỗi truy vấn cần thiết nào. Một handler RelayCommand sẽ công bố thông điệp này như thế này:

private void RelayCommandHandler() 
{ 
    //Logic for determining next view, then ... 
    Messenger.Default.Send(new NavigationMessage("ViewToNavigate")); 
} 

Cuối cùng, lớp xem cơ sở trông như thế này:

public class BasePage : PhoneApplicationPage 
{ 
    public BasePage() 
    { 
     Messenger.Default.Register<NavigationMessage>(this, NavigateToPage); 
    } 

    protected void NavigateToPage(NavigationMessage message) 
    { 
     //GetQueryString isn't shown, but is simply a helper method for formatting the query string from the dictionary 
     string queryStringParams = message.QueryStringParams == null ? "" : GetQueryString(message); 

     string uri = string.Format("/Views/{0}.xaml{1}", message.PageName, queryStringParams); 
     NavigationService.Navigate(new Uri(uri, UriKind.Relative)); 
    } 
} 

này là giả định một quy ước mà tất cả các quan điểm đang ở trong một "Views" thư mục trong thư mục gốc của ứng dụng. Điều này làm việc tốt cho ứng dụng của chúng tôi nhưng tất nhiên điều này có thể được mở rộng để hỗ trợ các kịch bản khác nhau về cách bạn tổ chức các quan điểm của mình.

+0

Đề xuất tuyệt vời, cảm ơn! –

+0

Tôi sẽ thừa nhận rằng tôi không quá quen thuộc với hệ thống Messenger mà MVVM-Light cung cấp.Upon phản ánh thêm, điều này không có nghĩa là tất cả các chế độ xem sẽ đăng ký và nghe điều hướng này không? –

+0

Tôi cho rằng đó có thể là một vấn đề. Tôi đang sử dụng kỹ thuật này trong ngữ cảnh của một ứng dụng Windows Phone 7, nơi tôi chỉ có một chế độ xem hoạt động tại một thời điểm để nó hoạt động hoàn hảo. Nếu bạn đang làm việc trong phiên bản Silverlight trên máy tính để bàn hoặc WPF và bạn có nhiều chế độ xem đang hoạt động cùng một lúc, tôi có thể thấy đây có thể là vấn đề. Sẽ phải suy nghĩ về điều đó một số chi tiết. –

6

Cảnh báo: khăng khăng MVVM người mới cảnh báo :) (Tôi rất mới để MVVM, nhưng thưởng thức nó rất nhiều cho đến nay.)

Tốt câu hỏi. Tôi đã thấy rằng nó hoàn toàn khả thi (nếu một chút xấu xí ở những nơi) để thử ra NavigationService và vượt qua một INavigationService cho một ViewModel. Trong thực tế, bạn thậm chí có thể làm cho giao diện đẹp hơn một chút với generics, để vượt qua trong một loại (như một đối số kiểu) chứ không phải là một chuỗi URI.

Tuy nhiên, tôi nhận thấy tôi đã phần nào bỏ lỡ khi nói đến nơi bạn đặt thêm dữ liệu liên quan đến điều hướng ... Tôi đã không tìm thấy một nơi tốt duy nhất để làm tất cả các mã hóa/unencoding để tuyên truyền nhà nước gọn gàng. Tôi nghi ngờ ViewModelFactory cũng có thể là một phần của phương trình đó ...

Vì vậy, không phải là giải pháp hoàn hảo - nhưng ít nhất ViewModel có thể chịu trách nhiệm về hành động "điều hướng ngay bây giờ" (hoặc "quay lại").

+0

Tôi cũng đang thưởng thức MVVM, howerver dường như có một số bit của các mẫu Silverlight không đặc biệt thân thiện với MVVM; điều hướng là một.Cảm ơn vì ý tưởng truyền một loại thay vì một chuỗi như "uri". có ý nghĩa hoàn hảo trong ngữ cảnh này. –

Các vấn đề liên quan