Giao diện ICommand
như sau:
public interface ICommand
{
// two methods
bool CanExecute(object parameter);
void Execute(object parameter);
// one event
event EventHandler CanExecuteChanged;
}
Sự kiện CanExecuteChanged
nên được nâng lên bất cứ lúc nào bạn muốn chỉ ra rằng phương pháp CanExecute
nên được kiểm tra/được gọi bởi WPF. Bất cứ ai thực hiện ICommand
nên nâng cao sự kiện và bất cứ ai cần phải làm mới trạng thái kích hoạt nút trên GUI (hệ thống WPF) nên đăng ký và xử lý sự kiện và nó gọi CanExecute
.
Trong lớp RelayCommand
Josh Smith, ông sử dụng WPF tích hợp trong CommandManager
lớp để nâng cao CanExecuteChanged
:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Về bản chất, WPF của CommandManager
là một singleton mà nghe cho tất cả các loại sự kiện được định tuyến: KeyUpEvent, MouseUpEvent, vv ... và sau đó nói với mọi người "điều gì đó thú vị đã xảy ra" bằng cách tăng sự kiện RequerySuggested
của nó. Vì vậy, nếu bạn đang sử dụng RelayCommand
, CanExecute
của bạn sẽ được gọi mỗi lần CommandManager
nghĩ rằng điều gì đó thú vị đã xảy ra trên GUI (ngay cả khi nó không liên quan gì đến bộ sưu tập của bạn). Nếu bạn có 50 lệnh, mỗi khi bạn khóa, nó sẽ kiểm tra lại tất cả 50 lệnh. Vì vậy, có, có thể là sự cố về hiệu suất. Tuy nhiên, nếu logic của bạn trong phương thức CanExecute
của bạn thực sự đơn giản, thì đó có thể là vấn đề không phải. Điểm Takeaway: không thực hiện cuộc gọi API cơ sở dữ liệu hoặc mạng trong phương thức CanExecute
.
Cách khác để cõng tắt CommandManager.RequerySuggested
để nâng cao sự kiện ICommand.CanExecuteChanged
là roll-bạn-của riêng phiên bản của RelayCommand
nơi bạn làm kiểm tra của riêng bạn và nâng cao CanExecuteChanged
bằng tay, hoặc nhìn vào lớp DelegateCommand
khuôn khổ của Prism, nơi họ không buộc vào CommandManager
và bạn phải tự nâng cao sự kiện CanExecuteChanged
mà bạn có thể thực hiện bằng cách tạo trình nghe cho PropertyChanged
và sau đó tăng CanExecuteChanged
trên lệnh.
Tôi đồng ý với @Will ở trên. RelayCommand
có thể sẽ hoạt động trên 80% thời gian mà không gặp sự cố. Nếu bạn bắt đầu tìm kiếm các vấn đề về hiệu suất, thì bạn có thể tạo phiên bản RelayCommand của riêng mình hoặc sử dụng Prism DelegateCommand
và tăng CanExecuteChanged
theo cách thủ công.
Có, nhưng chỉ khi bạn không tối ưu hóa sớm. – Will
Nhận xét của bạn có hơi mơ hồ không. – Tyrsius
Sẽ, tôi cũng không hoàn toàn hiểu. Xác thực của tôi là một lần lặp của khoảng 200 đối tượng - một chế độ xem dạng cây. Nó chỉ kiểm tra một thuộc tính đơn giản và không tốn nhiều thời gian khi chạy một lần. Mối quan tâm của tôi là nếu CanExecute được kích hoạt nhiều lần khiến mã chậm. Ai đó có thể vui lòng ném một số ánh sáng – ganeshran