2012-08-05 32 views
6

Hiện tại tôi đang học WPF và MVVM, tôi nghĩ rằng tôi có được hầu hết nó và cách nó hoạt động nhưng tôi đã gặp một số thứ về sử dụng RelayCommand (hoặc DelegateCommand) mà tôi không hiểu. Tôi nghĩ nó liên quan đến cách các đại biểu làm việc.Relaycommand và phương thức thực hiện không tham số

Xin lưu ý rằng mã bên dưới là tất cả chỉ trong các giải pháp kiểm tra tại thời điểm này, vì vậy không có mã trực tiếp. Ngoài ra tôi đang xem xét điều này cho các lệnh mà không yêu cầu một tham số như đóng và để hiểu tại sao nó hoạt động.

Vì vậy, nếu tôi lấy RelayCommand rằng Josh Smith tạo (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030) Tôi có thể thiết lập một lệnh như thế này:

RelayCommand updateTextContentCommand; 

public ICommand UpdateTextContentCommand 
{ 
    get 
    { 
     if (updateTextContentCommand == null) 
     { 
      updateTextContentCommand = new RelayCommand(
       param => this.UpdateTextContentCommand_Execute()); 
     } 
     return updateTextContentCommand; 
    } 
} 

với phương pháp thực hiện điều này:

public void UpdateTextContentCommand_Execute() 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

tôi đã sử dụng một ràng buộc đơn giản để một TextBlock để xem kết quả và lệnh được liên kết với một nút. Điều này hoạt động tốt. Những gì tôi không nhận được là việc sử dụng biểu thức lambda để tạo ra lệnh. Các Action<object> hy vọng một tham số phải không? vậy tại sao mã này hoạt động?

Nếu tôi thay đổi mã ở trên để

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

tôi nhận được những lỗi:

* Các quá tải tốt nhất phương pháp phù hợp cho 'MVVM.RelayCommandTesting.Framework.RelayCommand.RelayCommand (System.Action) có một số đối số không hợp lệ

Đối số 1: không thể chuyển đổi từ 'khoảng trống' thành 'System.Action' *

và loại bỏ các () sau Execute cho lỗi này:

Đối số 1: không thể chuyển đổi từ 'phương pháp nhóm' thành 'System.Action'

Nhưng nếu tôi thay đổi mã như thế này:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

public void UpdateTextContentCommand_Execute(object param) 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

nó tuân và chạy tốt. Nếu tôi thay đổi chế độ xem sử dụng CommandParameter thì tôi có thể sử dụng param để đặt nội dung văn bản bằng cách sử dụng phương pháp này, nhưng nếu tôi sử dụng kiểu lambda, tôi phải chuyển tham số vào dòng sao cho tham số này = = this.UpdateTextContentCommand_Execute(param).

Trong thử nghiệm của mình, tôi mã hóa cứng giá trị CommandParameter nhưng tôi đoán rất có thể dữ liệu sẽ được liên kết với thuộc tính của ViewModel trong hệ thống thực để bạn có thể chuyển tham số theo kiểu lambda.

Mọi người có thể giải thích tại sao phiên bản không tham số hoạt động với kiểu lambda không?

Cảm ơn bạn đã dành thời gian đọc nội dung này.

Dường như câu hỏi bên dưới cũng có một số câu hỏi về lambda nhưng tôi không thấy câu trả lời đó có câu hỏi của tôi.

Passing a parameter using RelayCommand defined in the ViewModel (from Josh Smith example)

+0

+1 cho câu hỏi chi tiết thể hiện rằng bạn đã thử một cái gì đó. –

+0

Chúc mừng. Tôi luôn cố gắng và nỗ lực khi đăng câu hỏi khi tôi thấy các câu hỏi như vậy hữu ích khi tôi đang tìm câu trả lời. – Kioshiki

Trả lời

8

Tham số nhà xây dựng là một đại biểu có chữ ký sau đây:.

void MethodName(T parameter) 

nơi tham số là loại T (trong trường hợp của RelayCommand này sẽ loại system.Object

Mã này:

param => this.UpdateTextContentCommand_Execute() 

là một biểu lambda rằng về cơ bản mở rộng này:

void AnonymousMethod(object param) 
{ 
    this.UpdateTextContentCommand_Execute(); 
} 

Vì vậy, trong trường hợp này bạn đi qua trong một tham số (param) bạn chỉ không sử dụng nó. Nếu bạn hiểu điều này thì bây giờ bạn sẽ nhận ra lý do tại sao các ví dụ khác của bạn hoạt động theo cách của chúng.

Ví dụ 1

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

Ở đây bạn đang gọi phương pháp mà trả về void. Hàm tạo đang mong đợi một cái gì đó phù hợp với đại biểu Action<T> do đó có lỗi.

Ví dụ 2

Nếu bạn sau đó loại bỏ các dấu ngoặc như thế này:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

Hãy suy nghĩ về điều này như là một chút như đăng ký vào một sự kiện:

myObject.myevent += new Action<object>(this.UpdateTextContentCommand_Execute); 

mà có thể được rút ngắn thành:

myObject.myevent += this.UpdateTextContentCommand_Execute; 

Vì vậy, các nhà xây dựng chấp nhận bất kỳ phương pháp mà có một chữ ký phù hợp với Action<T> đại biểu chữ ký tức là

void UpdateTextContentCommand_Execute(object parameter) 

phương pháp của bạn có chữ ký sau đây:

void UpdateTextContentCommand_Execute() 

Như bạn có thể nhìn thấy chữ ký don không phù hợp để trình biên dịch phàn nàn.

Khi bạn cập nhật phương thức UpdateTextContentCommand_Execute của mình để chấp nhận thông số đối tượng, chữ ký của nó bây giờ khớp với đó là lý do tại sao giờ đây nó hoạt động.

+0

Cảm ơn, nơi bạn sử dụng phương pháp ví dụ (AnonymousMethod) làm cho nó tất cả rơi vào vị trí cho tôi. Tôi nghĩ đó là một trường hợp 'không thể nhìn thấy cây gỗ'. Tôi đã không sử dụng biểu thức lambda nhiều nhưng tôi đã làm một chút với LINQ. Tôi chỉ không muốn thấy kết nối. – Kioshiki

+0

Tôi gặp vấn đề tương tự. Khi tôi có khoảnh khắc 'aha' đó mọi thứ rơi vào vị trí và biểu thức lambda đột nhiên trở nên dễ hiểu hơn rất nhiều. Tôi rất vui vì tôi có thể nói lên kinh nghiệm của tôi theo cách giúp đỡ người khác. –

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