2008-09-11 17 views
9

Tôi đang theo mẫu M-V-VM cho giao diện người dùng WPF của mình. Tôi muốn treo một lệnh vào sự kiện TextChanged của một TextBox đến một lệnh trong lớp ViewModel của tôi. Cách duy nhất tôi có thể quan niệm để hoàn thành nhiệm vụ này là kế thừa từ việc điều khiển TextBox và triển khai ICommandSource. Sau đó tôi có thể hướng dẫn lệnh được kích hoạt từ sự kiện TextChanged. Điều này có vẻ là quá nhiều công việc cho một cái gì đó mà dường như rất đơn giản.TextBox.TextChanged & ICommandSource

Có cách nào dễ hơn (hơn là phân lớp TextBox và triển khai ICommandSource) để kết nối sự kiện TextChanged với lớp ViewModel của tôi không?

Trả lời

18

Trước hết, bạn chắc chắn đã xem xét dữ liệu hai chiều ràng buộc với chế độ xem của mình, với UpdateSourceTrigger của PropertyChanged? Bằng cách đó, tài sản setter của tài sản bạn liên kết với sẽ được gọi mỗi khi văn bản được thay đổi?

Nếu điều đó không đủ, thì tôi sẽ giải quyết vấn đề này bằng cách sử dụng Hành vi được đính kèm. Trên Blog của Julian Dominguez, bạn sẽ tìm thấy một số article về cách thực hiện điều gì đó rất giống với Silverlight, điều này có thể dễ dàng thích ứng với WPF.

Về cơ bản, trong một lớp tĩnh (gọi là TextBoxBehaviours), bạn xác định Thuộc tính đính kèm được gọi là (có thể) TextChangedCommand thuộc loại ICommand. Kết nối một trình xử lý OnPropertyChanged cho thuộc tính đó và trong trình xử lý, hãy kiểm tra xem thuộc tính đang được đặt trên một TextBox hay chưa; nếu có, hãy thêm trình xử lý vào sự kiện TextChanged trên hộp văn bản sẽ gọi lệnh được chỉ định trong thuộc tính.

Sau đó, giả sử viewmodel của bạn đã được giao cho DataContext của Xem của bạn, bạn sẽ sử dụng nó như:

<TextBox 
    x:Name="MyTextBox" 
    TextBoxBehaviours.TextChangedCommand="{Binding ViewModelTextChangedCommand}" /> 
+1

Cảm ơn Sam - đôi khi tôi không thấy các tùy chọn đơn giản; mà trong trường hợp này là có textbox bị ràng buộc vào một thuộc tính chuỗi trong ViewModel của tôi. –

+0

Tôi không nghĩ rằng việc thêm logic vào setter của thuộc tính sẽ hoạt động. Bộ xử lý WPAM XAML sử dụng thuộc tính phụ thuộc trực tiếp thay vì đi qua trình bao bọc thuộc tính. Điều này có nghĩa là setter sẽ không bao giờ được gọi khi UI được cập nhật. (nguồn: http://msdn.microsoft.com/en-us/library/bb613563.aspx) – Greg

+2

Greg, tôi đang đề cập đến Setter của thuộc tính trong ViewModel mà thuộc tính dependency bị ràng buộc, không phải là setter của chính thuộc tính phụ thuộc. –

3

Bạn có thể không chỉ xử lý sự kiện TextChanged và thực hiện lệnh từ đó không?

private void _textBox_TextChanged(object sender, EventArgs e) 
{ 
    MyCommand.Execute(null); 
} 

Việc thay thế, như bạn nói, là để tạo ra một TextBox mà đóng vai trò như một nguồn lệnh, nhưng điều đó dường như quá mức cần thiết trừ khi nó là cái gì bạn đang lập kế hoạch về chia sẻ và tận dụng ở nhiều nơi.

8

Sử dụng sự kiện ràng buộc và phương pháp lệnh có thể không phải là điều đúng đắn để sử dụng. Lệnh này sẽ làm gì?

Bạn có thể muốn xem xét sử dụng một Databinding để một trường chuỗi trong máy ảo của bạn. Bằng cách này, bạn có thể thực hiện cuộc gọi đến một lệnh hoặc chức năng từ đó thay vì có giao diện người dùng.

<TextBox Text="{Binding WorldName}"/> 
.... 
public string WorldName 
{ 
    get 
    { 
     return WorldData.Name; 
    } 
    set 
    { 
     WorldData.Name = value; 
     OnPropertyChanged("WorldName"); 
     // CallYourCustomFunctionHere(); 
    } 
} 
+0

Cảm ơn Nidonocu. Câu trả lời của bạn cũng hoàn hảo, nhưng tôi đánh dấu câu trả lời của Sam là câu trả lời bởi vì anh ấy đã trả lời một chút trước bạn. Cảm ơn một lần nữa mặc dù! –