[英]Relaycommand ICommand.CanExecute not firing
我有以下問題:
我有一個帶有執行canexecute方法的中繼命令,但是每次我調用raisecanexecutechanged()時; 它在relaycommand中調用raisecanexecutechanged,為其設置一個新的委托,然后返回到視圖模型。
相同的設置適用於另一個視圖模型。 我檢查了1000次,有什么不同,但我什么也沒找到。
如果您能幫助我,我將不勝感激。
public RelayCommand UpdateAMSCommand { get; private set; }
public AMSSettingsViewModel(IEventAggregator eventAggregator)
{
UpdateAMSCommand = new RelayCommand(OnUpdateAMS, CanUpdateAms);
CustomAMSOffices.ListChanged += listChanged;
CustomAMSContacts.ListChanged += listChanged;
}
private void listChanged(object sender, ListChangedEventArgs e)
{
if (sender != null)
{
if (sender is BindingList<CustomAMSOffice>)
{
BindingList<CustomAMSOffice> temp = (BindingList<CustomAMSOffice>)sender;
if (temp.Count > _amsOfficesItemsCounter)
{
_amsOfficesItemsCounter = temp.Count;
for (int i = 0; i < temp.Count; i++)
{
temp[i].ErrorsChanged += RaiseCanExecuteChanged;
}
}
}
else if (sender is BindingList<CustomAMSContact>)
{
BindingList<CustomAMSContact> temp = (BindingList<CustomAMSContact>)sender;
if (temp.Count > _amsContactsItemsCounter)
{
_amsContactsItemsCounter = temp.Count;
for (int i = 0; i < temp.Count; i++)
{
temp[i].ErrorsChanged += RaiseCanExecuteChanged;
}
}
}
}
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private void RaiseCanExecuteChanged(object sender, DataErrorsChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private bool CanUpdateAms()
{
foreach (var cao in CustomAMSOffices)
{
if (!cao.Check() || cao.HasErrors)
{
return false;
}
}
foreach (var cac in CustomAMSContacts)
{
if (!cac.Check() || cac.HasErrors)
{
return false;
}
}
return true;
}
編輯:我使用的relaycommand: https : //github.com/briannoyes/WPFMVVM-StarterCode/blob/master/ZzaDashboard/ZzaDashboard/RelayCommand.cs
好的,我將要復制粘貼一些我正在使用的代碼,以便您應該能夠將它們彈出到您的項目中並使用。
首先,是RelayCommand()
類。 我從此msdn頁面取消了此代碼:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
現在,我們的ModelView.cs
類需要繼承自INotifyPropertyChanged
並將具有RaisePropertyChanged()
。 現在,我通常使它成為一個自己的文件,並讓我的所有ModelViews都繼承自該文件,這樣代碼可以更簡潔一些,但是您可以隨意做。
這是我的設置方法:
BaseViewModel.cs:
public class BaseViewModel : INotifyPropertyChanged
{
internal void RaisePropertyChanged(string prop)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
// Any other code we want all model views to have
}
現在,對於MainViewModel.cs,我們將繼承自BaseViewModel,在其中添加事件處理程序並運行它!
示例:ServerViewModel.cs
public class ServerViewModel : BaseViewModel
{
public RelayCommand BroadcastMessageCommand { get; set; }
private string _broadcastmessage;
public string broadcastmessage
{
get { return _broadcastmessage; }
set { _broadcastmessage = value; RaisePropertyChanged("broadcastmessage"); }
}
Server server;
public ServerViewModel()
{
server = new Server();
server.run();
BroadcastMessageCommand = new RelayCommand(BroadcastMessage, CanBroadcast);
}
private bool CanBroadcast(object param)
{
if (string.IsNullOrWhiteSpace(broadcastmessage))
return false;
if (!server.running)
return false;
return true;
}
public void BroadcastMessage(object param)
{
server.BroadcastMessage(broadcastmessage);
broadcastmessage = "";
RaisePropertyChanged("broadcastmessage");
}
}
現在,MainView.xaml中與Command="{Binding broadcastmessage}"
都將適當更新。 在我的情況下,我將其綁定到一個按鈕,並且如果消息為空或我們未連接到服務器,則該按鈕將被禁用。
希望有足夠的代碼示例使您朝正確的方向前進! 如果您有任何疑問,請告訴我。
讓我們嘗試盡可能地簡化代碼,直到我們能夠正常工作,然后再慢慢添加代碼,直到找到造成麻煩的代碼為止。
因此,讓我們將其簡化為准系統,看看我們是否有任何成功。 試試這個代碼:
public RelayCommand UpdateAMSCommand { get; private set; }
public AMSSettingsViewModel(IEventAggregator eventAggregator)
{
UpdateAMSCommand = new RelayCommand(OnUpdateAMS, CanUpdateAms);
CustomAMSOffices.ListChanged += listChanged;
CustomAMSContacts.ListChanged += listChanged;
}
private void listChanged(object sender, ListChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private void RaiseCanExecuteChanged(object sender, DataErrorsChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
// This will simply flip from true to false every time it is called.
private bool _canupdate = false;
private bool CanUpdateAms()
{
_canupdate = !_canupdate;
return _canupdate;
}
編輯:我不知道為什么它不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.