3

首先,这是我在 SO 上的第一篇文章,所以要温柔;)

我有一个非常简单的 WPF 应用程序,其菜单包含两个选项和不同视图中的一些按钮,其中大多数都与 Microsoft.TeamFoundation.MVVM.RelayCommand 数据绑定。在我的计算机上调试时一切正常,在运行内置的 exe 时它运行良好,在我同事的计算机上构建的版本运行良好,但是当在我办公室的另一台计算机上测试时,这些RelayCommands 都不会触发......

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());
    }
}

关于电脑的一些信息:

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

该解决方案专为目标框架 4.5 和处理器架构 x86 构建。其他数据绑定,比如上面的 IsEnabled 和各种文本属性,似乎工作正常。

请告诉我是否可以提供任何其他信息!

更新:我自己实现了 RelayCommand,效果很好:

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);
    }
}

我不知道我的实现与 TeamFoundation 的实现有什么区别。

4

2 回答 2

0

不确定这是否可以帮助您,但我遇到了类似的问题,并通过在命令初始化期间显式触发 PropertyChanged 事件来解决它:

base.RaisePropertyChanged("QuitCommand");

当然,上面的方法只有在你有一个实现INotifyPropertyChanged接口的基类时才可用。您可以从 Josh Smith 的MVVM Foundation框架中获取它。

完整的示例代码如下:

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());
}

这里有趣的是,我很确定您的原始代码在一段时间前对我来说非常好(不同的机器、环境、操作系统等)。

看起来在特定情况下,某些东西阻止了 View 类在 ViewModel 创建/启动过程中读取命令(?)属性。这需要您手动告诉 View 它应该读取目标 ViewModel 属性。

于 2013-06-09T09:57:05.493 回答
-1

return new relaycommand 非常糟糕——因为你总是创建一个新实例。

如果需要,请使用延迟初始化。

private Lazy<RelayCommand> _quitcommand;

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


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

编辑:您还可以在运行时使用Snoop检查您的绑定

于 2013-06-02T07:34:05.193 回答