2010-06-03 9 views

Trả lời

15

Đây là một trong những câu trả lời khó hiểu nhất mà tôi không thực sự trả lời câu hỏi của bạn, nhưng thay vào đó, hãy hướng dẫn bạn về những gì bạn nên làm khác đi. Thành thật xin lỗi về điều đó. Ở đây đi:

Nếu bạn thấy mình ở vị trí mà bạn cần nhận được đối tượng người gửi trong chế độ xem, thì có thể bạn nên làm điều gì đó khác. Bằng cách tham khảo, nói, một Button hoặc một ListBox trong viewmodel của bạn, bạn đã làm cho viewmodel đó nhận thức được các khái niệm UI mà nó không nên biết gì về nó. Đề xuất của tôi là thay vào đó kết nối với sự kiện trong trang code-behind, tìm hiểu những gì bạn cần biết về người gửi hoặc những gì không, và sau đó thực thi lệnh viewmodel theo lập trình. Điều đó cũng phá vỡ các "quy tắc" MVVM, nhưng IMHO nó là một hack chặt chẽ hơn nhiều so với tham chiếu người gửi trong viewmodel của bạn.

+0

Cũng giống như VM không được hiển thị Visibilty (và thay vào đó sử dụng trình chuyển đổi trong XAML), có thể có cách nào đó để sử dụng trình chuyển đổi để chuyển sang một cách khác ... thành loại không xem? –

+0

Đề xuất của bạn cũng vi phạm quy tắc MVVM như thế nào? Có vẻ ổn với tôi. –

+0

Tôi nghĩ rằng vấn đề chính của tôi vào thời điểm đó là nó quá phức tạp so với việc chỉ ràng buộc nút (trong giao diện) với lệnh trong máy ảo. Nhìn vào nó bây giờ, tôi nghĩ rằng bạn là đúng. Nó không thực sự phá vỡ bất kỳ quy tắc nào. –

9

Tôi đã gặp sự cố tương tự nhưng chỉ cần thiết để nhận EventArgs. Rất vui, điều này là vô lý đơn giản một khi tôi tìm thấy câu trả lời trong một chủ đề ở đây tại Stack tràn.

<cmd:EventToCommand Command="{Binding SomeCommand, Mode=OneWay}" PassEventArgsToCommand="True"/> 

Khi bạn biết về cài đặt "PassEventArgsToCommand" ma thuật đó, bạn sẽ có vàng. Chỉ cần sử dụng một RelayCommand<type> thay vì một RelayCommand đơn giản.

Tôi hy vọng điều này sẽ hữu ích.

+5

Chỉ muốn bình luận về điều đó: PassEventArgsToCommand không phải là rất sạch sẽ, bởi vì nó phá vỡ sự tách biệt của mối quan tâm bằng cách mang một lớp UI (EventArgs) vào VM. Sử dụng điều này làm cho VM của bạn ít kiểm tra hơn. Tuy nhiên, có các kịch bản (ví dụ: kéo & thả), nơi bất kỳ thứ gì khác thậm chí còn bẩn hơn. Đây là lý do tại sao tôi thêm vào EventToCommand. Sử dụng với rất nhiều chăm sóc mặc dù! – LBugnion

+2

Mặc dù PassEventArgsToCommand có thể không sạch, nhưng tôi thấy hữu ích khi cố gắng thêm hỗ trợ SkyDrive vào ứng dụng WP7 của tôi. Nút đăng nhập chuyển thông tin phiên trực tiếp qua sự kiện args. Tôi có lẽ có thể xử lý các sự kiện trong code-behind, đặt thuộc tính Session vào ViewModel và sau đó gọi một lệnh. PassEventArgsToCommand giúp viết mã dễ hiểu. – rams

5

Điều này có thể được thực hiện bằng cách liên kết người gửi với tham số lệnh.

<command:EventToCommand 
       Command="{Binding CommandName}" 
       CommandParameter="{Binding RelativeSource= 
             { RelativeSource FindAncestor, 
              AncestorType={x:Type TypeOfSender}, 
              AncestorLevel=1}}" 
       PassEventArgsToCommand="True" > 
</command:EventToCommand> 
+1

Tôi upvoted này bởi vì trong khi Henrik là chính xác trong việc giải thích rằng điều này không nên được thực hiện, thế giới không phải là hoàn hảo và đạt được MVVM tinh khiết là đôi khi không thể. Ví dụ, nếu bạn muốn một Textbox chọn tất cả văn bản khi nó nhận được tiêu điểm, bạn sẽ cần TextBox để gọi thành viên SelectAll() của nó. Nó chắc chắn có thể làm được trong MVVM nhưng nó sẽ tạo ra mã phức tạp điên rồ, trong khi giải pháp này là, trong một số trường hợp, "đủ tốt". Tôi đồng ý rằng hành vi này nên được khuyến khích càng nhiều càng tốt, nhưng đôi khi bạn chỉ cần thực dụng và sửa lỗi như thế này, trong khi xấu xí, hoạt động. – Bas

+2

Ví dụ khác: điều khiển WPB WebBrowser. bạn có thể liên kết lệnh với sự kiện Điều hướng, nhưng nếu bạn thực sự muốn làm điều gì đó với câu trả lời http, bạn cần tham chiếu đến chính trình duyệt, vì thông tin đó không có trong eventargs. – Bas