2013-08-26 27 views
5

Tôi có một AddClientViewModel được tham chiếu bởi 2 khung nhìn (AddClientView và SuggestedAddressesView). AddClientView là một biểu mẫu có một trường cho một địa chỉ. Biểu mẫu có nút xác thực hợp lệ địa chỉ đã nhập bằng Mã hóa địa lý. Nếu có nhiều hơn một địa chỉ được trả về, khung nhìn SuggestedAddressesView sẽ mở ra.Mở/Đóng Xem từ ViewModel

Dưới đây là làm thế nào tôi hiện đang làm việc đó:

AddClientViewModel:

private void ValidateExecute(object obj) 
    { 
     SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress)); 

     .... 

     if (SuggestedAddresses.Count > 0) 
     { 
      var window = new SuggestedAddressesView(this); 
      window.DataContext = this; 
      window.Show(); 
     } 
    } 

Dưới đây là các nhà xây dựng SuggestedAddressesView nơi AddClientViewModel thừa hưởng từ ViewModelBase

public SuggestedAddressesView(ViewModelBase viewModel) 
    { 
     InitializeComponent(); 
     viewModel.ClosingRequest += (sender, e) => this.Close(); 
    } 

Vấn đề khác mà tôi đang gặp là khi tôi gọi OnClosingRequest() từ AddClientViewModel ... cả AddClientView và SuggestedAddressesView sẽ đóng lại. Tôi biết điều này xảy ra vì cả hai lượt xem đều tham chiếu cùng ViewModel. Đây không phải là hành vi tôi muốn. Tôi muốn có thể đóng một cửa sổ độc lập.

Đang mở Chế độ xem từ cấu trúc MVVM phù hợp ViewModel và làm cách nào để tôi có thể đóng cửa sổ một cách độc lập?

Trả lời

5

Ngay sau khi bạn đề cập đến các yếu tố giao diện người dùng (Trong trường hợp này View) từ VM, bạn sẽ dựa trên Nguyên tắc MVVM gợi ý. Chỉ với điều đó chúng ta có thể biết việc tạo đối tượng Window trong VM là sai.

Vì vậy, bây giờ vào chấn chỉnh này:

  • Trước hết cố gắng giữ 1 Xem < -> 1 VM trong ứng dụng của bạn. Nó sạch hơn và cho phép bạn chuyển đổi các triển khai Chế độ xem với cùng một logic rất dễ dàng. Thêm nhiều chế độ xem vào cùng một máy ảo ngay cả khi không phải "đột phá" chỉ làm cho nó vụng về.
  • Vì vậy, bây giờ bạn có AddClientViewSuggestedAddressesView bằng máy ảo của riêng mình. Tuyệt quá!

Thực hiện một Xem Open/Close từ VM:

  • Kể từ khi chúng tôi không thể truy cập Xem trực tiếp từ máy ảo của chúng tôi (để phù hợp với tiêu chuẩn), chúng ta có thể sử dụng các phương pháp như sử dụng một Messenger (MVVM Ánh sáng), EventAggregator (PRISM) và cứ như vậy để gửi một "thông báo" từ máy ảo đến Chế độ xem khi bạn cần mở/đóng Chế độ xem và thực hiện thao tác thực tế trong Chế độ xem.
  • Bằng cách này, VM chỉ khởi tạo thông báo và có thể được kiểm tra đơn vị tiền phạt cho cùng một thao tác và không tham chiếu bất kỳ phần tử giao diện người dùng nào.

Sử dụng một "Messenger" cách tiếp cận để xử lý Xem mở:

  • Theo logic của bạn, nó là AddClientViewModel mà sẽ phải yêu cầu cho SuggestedAddressesView sẽ được mở.
  • Do đó, khi bạn phát hiện SuggestedAddresses.Count > 0, bạn sẽ gửi thư đến số AddClientView yêu cầu mở thư SuggestedAddressesView.
  • Trong AddClientView.xaml.cs khi nhận được thông báo này, bạn sẽ làm những gì bạn hiện đang làm trong VM. Tạo một đối tượng của SuggestedAddressesView và gọi .Show() trên đó.
  • Một bước bổ sung bạn sẽ thêm trong quy trình của bước trên là chỉ định DataContext của SuggestedAddressesViewSuggestedAddressesViewModel.

Vậy đó. Bây giờ những gì bạn có là, khi AddClientViewModel muốn hiển thị SuggestedAddressesView, nó sẽ gửi một tin nhắn đến Xem riêng của nó và Chế độ xem lần lượt tạo và hiển thị số SuggestedAddressesView. Bằng cách này, VM không tham chiếu bất kỳ View nào và chúng tôi vẫn giữ các tiêu chuẩn MVVM.

Sử dụng một "Messenger" cách tiếp cận để xử lý Xem gần:

  • bế một View là khá đơn giản. Một lần nữa khi bạn cần đóng View từ máy ảo, bạn gửi một tin nhắn đến View của chính nó yêu cầu nó được đóng lại.
  • Khi nhận được thông báo này, Chế độ xem khá nhiều tự đóng qua .Hide()/.Close() hoặc bất kỳ cách nào khác bạn muốn loại bỏ nó.

Trong mỗi máy ảo này xử lý việc đóng Chế độ xem của riêng nó và bạn không có bất kỳ phụ thuộc kết nối nào.

Bạn có thể sử dụng this làm điểm bắt đầu để hướng dẫn bạn xử lý "thư" cho phương pháp này. nó có một bản tải xuống kèm theo, bạn có thể xem và xem cách hoạt động của Messenger. Điều này là với MVVM Light, nếu bạn không sử dụng nó hoặc sử dụng cái gì khác/thực hiện MVVM của riêng bạn, hãy sử dụng nó như một hướng dẫn để giúp bạn đạt được những gì bạn cần.

+0

Được rồi, điều đó có ý nghĩa! Vấn đề tôi gặp phải là tôi muốn thông tin được thu thập từ ** SuggestedAddressesView ** sẽ được chuyển đến ** AddClientViewModel ** (vì vậy tại sao tôi sử dụng 1 VM cho 2 Chế độ xem). Lý do tôi làm điều này là vì Địa chỉ được chọn trong ** SuggestedAddressesView ** được gán cho một Khách hàng được định nghĩa trong ** AddClientViewModel **. – francisg3

+1

@ francisg3 xem liên kết ví dụ tôi đã đăng. Nếu bạn nhận được ví dụ ở đó, 'Cửa sổ' thứ hai đã mở thông tin chuyển tiếp Modal/Non-Modal trở lại MainWindow. Đây là quá trình bạn sẽ sử dụng cho yêu cầu của bạn. Bạn sẽ sử dụng khá nhiều Messenger để gửi tin nhắn (ở đây thông báo sẽ là dữ liệu bạn muốn gửi từ SuggestedAddressViewModel tới AddClientViewModel) – Viv

0

bạn có thể sử dụng RelayCommand để bạn gửi các thông số như sau:

Command="{Binding CloseWindowCommand, Mode=OneWay}" 
CommandParameter="{Binding ElementName=TestWindow}" 

Bằng cách sử dụng này, bạn có thể đóng các quan điểm cá nhân.

Ví dụ:

public ICommand CloseCommand 
    { 
     get 
     { 
      return new RelayCommand(OnClose, IsEnable); 
     } 
    } 

public void OnClose(object param) 
    { 
     AddClientView/SuggestedAddressesView Obj = param as AddClientView/SuggestedAddressesView; 
     obj.Close(); 
    } 
0

Để mở cửa sổ từ ViewModel:

Tạo lớp NavigationService.cs để mở cửa sổ: Hãy NavigationService.cs

Bây giờ đưa mã sau đây trong tập tin lớp.

public void ShowWindow1Screen(Window1ViewModel window1ViewModel) 
     { 
      Window1= new Window1(); 
      Window1.DataContext = window1ViewModel; 
      Window1.Owner = Window1View; 
      Window1.ShowDialog(); 
     } 

rồi. Tạo cá thể của tệp MainWindowViewModel của lớp NavigationService.cs. Sau đó,

Window1ViewModel window1ViewModel = new Vindow1ViewModel(); 
window1ViewModel.Name = MainWindowTextValue; 
NavigationService navigationService = new NavigationService(); 
navigationService.ShowWindow1Screen(window1ViewModel); 
Các vấn đề liên quan