繁体   English   中英

RelayCommand ICommand.CanExecute不触发

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM