RelayCommand not firing on some computers

蹲街弑〆低调 提交于 2019-12-23 18:50:35

问题


First of all, this is my first post on SO, so be gentle ;)

I have a very simple WPF application with a menu with two options and some buttons in different Views, most of these have data bindings to a Microsoft.TeamFoundation.MVVM.RelayCommand. When debugging on my computer it all works fine, when running the built exe it works fine, on my colleagues computer the built version works fine, but when testing on another computer at my office none of these RelayCommands will fire...

XAML:

//Menu item
<MenuItem Header="Quit" Command="{Binding QuitCommand}" />

//Button
<Button Content="Update" Command="{Binding UpdateCommand}" 
     IsEnabled="{Binding Ready}" Height="30" />

C#:

//Menu item
public ICommand QuitCommand 
{
    get
    {
        return new RelayCommand(() => Quit());
    }
}

//Button
public ICommand UpdateCommand
{
    get
    {
        return new RelayCommand(() => Update());
    }
}

Some info about the computers:

My computer: Win8 Pro 64, .NET 4.5
My colleagues computer: Win7 Pro 64, .NET 4.5
Office computer: Win7 Pro 32, .NET 4.5

The solution is built for target framework 4.5 and processor architecture x86. Other data bindings, like the one for IsEnabled above, and various text properties, seem to work fine.

Please tell me if I can provide any other information!

UPDATE: I made my own implementation of RelayCommand which works fine:

public class RelayCommand : ICommand
{
    readonly Action<object> mExecute;
    readonly Predicate<object> mCanExecute;

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        mExecute = execute;
        mCanExecute = canExecute;
    }

    public RelayCommand(Action<object> execute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        mExecute = execute;
        mCanExecute = delegate { return true; };
    }

    public RelayCommand(Action execute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        mExecute = new Action<object>(param => execute());
        mCanExecute = delegate { return true; };
    }

    public bool CanExecute(object parameter)
    {
        return mCanExecute == null ? true : mCanExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        mExecute(parameter);
    }
}

I don't know what the difference between my implementation and the one from TeamFoundation is.


回答1:


Not sure if this can help you but I had a similar problem and solved it with explicitly firing PropertyChanged event during the command initialization:

base.RaisePropertyChanged("QuitCommand");

Of course above method is only available while you have a base class which implements INotifyPropertyChanged interface. You can grab it e.g. from Josh Smith's MVVM Foundation framework.

Full sample code could be as follows:

private ICommand _quitCommand;

//Menu item
public ICommand QuitCommand 
{
    get { return _quitCommand; }
    private set
    {
        if (value == _quitCommand) return;

        _quitCommand = value;
        base.RaisePropertyChanged("QuitCommand");        
    }
}

public MyViewModel()
{
    QuitCommand = new RelayCommand(() => Quit());
}

The funny thing here is that I'm pretty sure your original code was working for me perfectly fine some time ago (different machine, environment, OS, etc.).

It looks like in specific situations something is preventing View class from reading command (?) properties at the ViewModel creation / start-up process. This requires from you to manually tell a View that it should read a target ViewModel property.




回答2:


return new relaycommand is very bad - because you always create a new instance.

use lazy initialization if you want.

private Lazy<RelayCommand> _quitcommand;

//ctor
_quitcommand = new Lazy<RelayCommand>(()=> new RelayCommand(() => Quit()));


public ICommand QuitCommand 
{
  get
  {
    return _quitcommand.Value;
  }
}

EDIT: you can also check your binding at runtime with Snoop



来源:https://stackoverflow.com/questions/16857547/relaycommand-not-firing-on-some-computers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!