C# RelayCommand不在某些计算机上启动

C# RelayCommand不在某些计算机上启动,c#,wpf,mvvm,relaycommand,C#,Wpf,Mvvm,Relaycommand,首先,这是我的第一篇关于SO的帖子,所以请温柔一点;) 我有一个非常简单的WPF应用程序,它有一个菜单,有两个选项,在不同的视图中有一些按钮,其中大多数都有到Microsoft.TeamFoundation.MVVM.RelayCommand的数据绑定。在我的电脑上调试时,一切正常,在运行内置exe时,一切正常,在我同事的电脑上,内置版本正常,但在我办公室的另一台电脑上测试时,这些RelayCommands都不会启动 XAML: 有关计算机的一些信息: My computer: Win8 Pr

首先,这是我的第一篇关于SO的帖子,所以请温柔一点;)

我有一个非常简单的WPF应用程序,它有一个菜单,有两个选项,在不同的视图中有一些按钮,其中大多数都有到Microsoft.TeamFoundation.MVVM.RelayCommand的数据绑定。在我的电脑上调试时,一切正常,在运行内置exe时,一切正常,在我同事的电脑上,内置版本正常,但在我办公室的另一台电脑上测试时,这些RelayCommands都不会启动

XAML:

有关计算机的一些信息:

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,效果很好:

公共类RelayCommand:ICommand
{
只读操作mExecute;
只读谓词mCanExecute;
公共RelayCommand(操作执行,谓词canExecute)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
mExecute=执行;
mCanExecute=canExecute;
}
公共中继命令(操作执行)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
mExecute=执行;
mCanExecute=delegate{return true;};
}
公共中继命令(操作执行)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
mExecute=新操作(param=>execute());
mCanExecute=delegate{return true;};
}
公共布尔CanExecute(对象参数)
{
返回mCanExecute==null?true:mCanExecute(参数);
}
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
public void Execute(对象参数)
{
mExecute(参数);
}
}

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

返回新的relaycommand非常糟糕-因为您总是创建新实例

如果需要,可以使用延迟初始化

private Lazy<RelayCommand> _quitcommand;

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


public ICommand QuitCommand 
{
  get
  {
    return _quitcommand.Value;
  }
}
private Lazy\u命令;
//执行器
_quitcommand=newlazy(()=>newrelaycommand(()=>Quit());
公共ICommand命令
{
得到
{
返回_quitcommand.Value;
}
}

编辑:您还可以在运行时使用

检查绑定。不确定这是否有帮助,但我遇到了类似的问题,并在命令初始化期间通过显式触发PropertyChanged事件解决了此问题:

base.RaisePropertyChanged("QuitCommand");
当然,只有当您有一个实现
INotifyPropertyChanged
接口的基类时,上述方法才可用。您可以从Josh Smith的框架中获取它

完整的示例代码可以如下所示:

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());
}
有趣的是,我很确定你的原始代码在一段时间前对我来说还很好(不同的机器、环境、操作系统等等)


看起来在特定情况下,视图类无法在ViewModel创建/启动过程中读取命令(?)属性。这需要您手动告诉视图它应该读取目标ViewModel属性。

您如何知道每次都返回一个新实例?这不是问题所在吗?顺便说一句,我的解决方案在我的项目的每台机器上都有效。请使用Snoop并在运行时检查不起作用的绑定。也许你还能找到更多information@blindmeis尽管我认为这是一种糟糕的做法,可能会对绑定的财产产生副作用,它所做的只是实例化一个调用相同方法的新命令,我几乎看不出这在不同的机器上有什么不同。就像我说的,我在我的项目中这样做,它在所有的机器上运行,我们有很多不同的计算机。也许Moggixx应该只使用一个命令来设置一个测试项目,以检查该命令是否正常工作。我已经用我自己在另一台计算机上运行的RelayCommand实现更新了原始帖子,没有改变每次都返回一个新实例的做法。虽然我也改变了这一点,但现在,因为我同意这似乎是一种不好的做法。。。我有时间的时候会试试史努比。
private Lazy<RelayCommand> _quitcommand;

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


public ICommand QuitCommand 
{
  get
  {
    return _quitcommand.Value;
  }
}
base.RaisePropertyChanged("QuitCommand");
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());
}