2012-04-12 23 views
48

Vì vậy, tôi đã tìm kiếm xung quanh và không thể tìm ra chính xác cách thực hiện việc này. Tôi đang tạo điều khiển người dùng bằng MVVM và muốn chạy lệnh trên sự kiện 'Đã tải'. Tôi nhận ra điều này đòi hỏi một chút mã phía sau, nhưng tôi không thể tìm ra những gì cần thiết. Lệnh này nằm trong ViewModel, được đặt làm datacontext của khung nhìn, nhưng tôi không chắc chắn chính xác cách định tuyến này vì vậy tôi có thể gọi nó từ mã phía sau của sự kiện được nạp. Về cơ bản những gì tôi muốn là một cái gì đó như thế này ...Lệnh gọi từ mã số Behind

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    //Call command from viewmodel 
} 

Nhìn xung quanh tôi dường như không thể tìm thấy cú pháp cho điều này ở bất cứ đâu. Tôi có cần phải ràng buộc lệnh trong xaml đầu tiên để có thể tham khảo nó? Tôi nhận thấy các tùy chọn lệnh ràng buộc trong một điều khiển người dùng sẽ không cho phép bạn liên kết các lệnh như bạn có thể trong vòng một cái gì đó giống như một nút ...

<UserControl.CommandBindings> 
    <CommandBinding Command="{Binding MyCommand}" /> <!-- Throws compile error --> 
</UserControl.CommandBindings> 

tôi chắc chắn rằng có một cách đơn giản để làm điều này, nhưng tôi có thể' t cho cuộc sống của tôi con số nó ra.

Trả lời

101

Vâng, nếu DataContext đã được thiết lập, bạn có thể cast nó và gọi lệnh:

var viewModel = (MyViewModel)DataContext; 
if (viewModel.MyCommand.CanExecute(null)) 
    viewModel.MyCommand.Execute(null); 

(Thay đổi tham số khi cần thiết)

+0

Vâng, đó là chính xác những gì tôi cần, tôi biết có một cách dễ dàng. Cảm ơn! –

+0

@KDiTraglia: Bạn được chào đón, vui vì điều đó đã giúp ích. –

+0

Bạn nên kiểm tra xem viewModel có rỗng không trước khi cố truy cập MyCommand. Tôi biết giải pháp của tôi không, nhưng của bạn nó là câu trả lời chấp nhận vì vậy nó có lẽ nên ở trong đó. – Alain

1

Hãy thử điều này:

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    //Optional - first test if the DataContext is not a MyViewModel 
    if(!this.DataContext is MyViewModel) return; 
    //Optional - check the CanExecute 
    if(!((MyViewModel) this.DataContext).MyCommand.CanExecute(null)) return; 
    //Execute the command 
    ((MyViewModel) this.DataContext).MyCommand.Execute(null) 
} 
+2

Bạn không nên gọi một Lệnh mà không đảm bảo rằng nó có thể được thực thi trước. –

+0

Nếu bạn chỉ sử dụng CanExecute để xác định liệu người dùng có thể thực hiện nó (tức là ràng buộc với trạng thái đã bật của nút) không có gì sai với nó. – Alain

+3

Với một nút điều khiển đảm bảo rằng lệnh này không bao giờ được thực hiện bất cẩn, nếu bạn thực hiện nó theo cách thủ công, bạn cần phải tự lo cho chính mình. –

3

Lời nói đầu: Không biết nhiều hơn về các yêu cầu của bạn, nó có vẻ giống như một mùi mã để thực hiện một lệnh từ mã sau khi tải. Có phải là một cách tốt hơn, MVVM-khôn ngoan.

Nhưng, nếu bạn thực sự cần phải làm điều đó trong mã phía sau, một cái gì đó như thế này có lẽ sẽ làm việc (lưu ý: Tôi không thể kiểm tra điều này vào lúc này):

private void UserControl_Loaded(object sender, RoutedEventArgs e)  
{ 
    // Get the viewmodel from the DataContext 
    MyViewModel vm = this.DataContext as MyViewModel; 

    //Call command from viewmodel  
    if ((vm != null) && (vm.MyCommand.CanExecute(null))) 
     vm.MyCommand.Execute(null); 
} 

Again - cố gắng tìm một cách tốt hơn ...

+1

Khi tìm kiếm về chủ đề, thực sự không có cách nào dễ dàng, và sự đồng thuận chung mà tôi đã thấy là một đoạn mã nhỏ đằng sau không bao giờ giết bất cứ ai. –

+1

@KDiTraglia - đúng, nhưng nói chung, "ít mã phía sau" thường đề cập đến các hành động chỉ ảnh hưởng đến chính Chế độ xem (tức là những thứ như chọn tất cả văn bản trong hộp văn bản khi nó lấy tiêu điểm). Ở đây, bạn đang tương tác trực tiếp với ViewModel từ mã phía sau của View, điều này phá vỡ nguyên tắc MVVM. –

1

Tôi có một giải pháp nhỏ gọn hơn mà tôi muốn chia sẻ. Bởi vì tôi thường thực hiện các lệnh trong ViewModels của mình, tôi đã mệt mỏi vì viết cùng một câu lệnh if. Vì vậy, tôi đã viết một phần mở rộng cho giao diện ICommand.

using System.Windows.Input; 

namespace SharedViewModels.Helpers 
{ 
    public static class ICommandHelper 
    { 
     public static bool CheckBeginExecute(this ICommand command) 
     { 
      return CheckBeginExecuteCommand(command); 
     } 

     public static bool CheckBeginExecuteCommand(ICommand command) 
     { 
      var canExecute = false; 
      lock (command) 
      { 
       canExecute = command.CanExecute(null); 
       if (canExecute) 
       { 
        command.Execute(null); 
       } 
      } 

      return canExecute; 
     } 
    } 
} 

Và đây là cách bạn sẽ thực hiện lệnh trong mã:

((MyViewModel)DataContext).MyCommand.CheckBeginExecute(); 

Tôi hy vọng điều này sẽ tăng tốc độ phát triển của bạn nhiều hơn chỉ là một chút nhỏ. :)

P.S. Đừng quên bao gồm không gian tên của ICommandHelper. (Trong trường hợp của tôi là SharedViewModels.Helpers)