C# RelayCommand赢得';单击按钮时不执行
我在这个问题上纠缠了几个小时。我正在尝试在WPF中实现MVVM样式的Word加载项。我没有使用MVVM工具包。我有一个WPF用户控件,它停靠在WinForm中。虽然我能够在win表单中看到WPF用户控件并与之交互,但当我单击按钮时,绑定到WPF按钮的通用C# RelayCommand赢得';单击按钮时不执行,c#,wpf,xaml,mvvm,relaycommand,C#,Wpf,Xaml,Mvvm,Relaycommand,我在这个问题上纠缠了几个小时。我正在尝试在WPF中实现MVVM样式的Word加载项。我没有使用MVVM工具包。我有一个WPF用户控件,它停靠在WinForm中。虽然我能够在win表单中看到WPF用户控件并与之交互,但当我单击按钮时,绑定到WPF按钮的通用RelayCommand将不会执行。RelayCommand位于ViewModel.cs中,视图的DataContext通过代码隐藏进行设置。我肯定我在做一些愚蠢的事情,但是我不知道它是什么,因此也不知道为什么RelayCommand属性的get
RelayCommand
将不会执行。RelayCommand
位于ViewModel.cs中,视图的DataContext
通过代码隐藏进行设置。我肯定我在做一些愚蠢的事情,但是我不知道它是什么,因此也不知道为什么RelayCommand
属性的get{}
不会被执行。请参阅下面的代码。提前感谢您的帮助
RelayCommand.cs(代码片段不包括名称空间,包括语句)
ViewModel.cs(不包括某些代码。仅显示相关的RelayCommand)
//
///SubmitCommentCommand负责与UI交互以提交注释。
///
///返回一个RelayCommand,该命令执行一个方法来保存注释框中的注释
公共ICommand SubmitCommentCommand
{
得到
{
返回_submitcommonCommand??(_submitcommonCommand=newrelaycommand(param=>this.SaveComment());
}
}
我通过在XAML而不是.cs文件中告诉模型数据上下文解决了这个问题
首先:告诉模型您放置视图模型的名称空间,我的如下所示:
xmlns:Local="clr-namespace:MKPL.Views.A01.S020"
Second:在XAML资源中添加ViewModel,如:
<UserControl.Resources>
<Local:ViewModel x:Key="dvm"/>
</UserControl.Resources>
Fourth:在按钮代码中添加如下数据上下文:
<Button Grid.Column="2" x:Name="SubmitButton" Command="{Binding Path=SubmitCommentCommand, Source={StaticResource dvm}}"
Content="Submit" HorizontalAlignment="Right" Margin="5"/>
希望它能帮助您我通过在XAML而不是.cs文件中告诉模型数据上下文解决了这个问题
首先:告诉模型您放置视图模型的名称空间,我的如下所示:
xmlns:Local="clr-namespace:MKPL.Views.A01.S020"
Second:在XAML资源中添加ViewModel,如:
<UserControl.Resources>
<Local:ViewModel x:Key="dvm"/>
</UserControl.Resources>
Fourth:在按钮代码中添加如下数据上下文:
<Button Grid.Column="2" x:Name="SubmitButton" Command="{Binding Path=SubmitCommentCommand, Source={StaticResource dvm}}"
Content="Submit" HorizontalAlignment="Right" Margin="5"/>
希望它能帮助您更详细地了解MVVM和RelayCommand:
您不必在Xaml中声明ViewModel,这主要是在应用程序根级别以编程方式完成的,可能需要一些DI
当坚持这一点时,您的RelayCommand应如下所示:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#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 // Constructors
#region ICommand Members
[DebuggerStepThrough]
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 // ICommand Members
}
public class GenericRelayCommand<T> : ICommand
{
private readonly Action<T> _execute;
public Predicate<T> CanExecuteFunc { get; private set; }
public GenericRelayCommand(Action<T> execute) : this(execute, p => true)
{}
public GenericRelayCommand(Action<T> execute, Predicate<T> canExecuteFunc)
{
_execute = execute;
CanExecuteFunc = canExecuteFunc;
}
public bool CanExecute(object parameter)
{
var canExecute = CanExecuteFunc((T)parameter);
return canExecute;
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Orientation="Horizontal">
<TextBox Name="textBox"
Width="200"
Text="{Binding Comment,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<Button x:Name="SubmitButton1"
Grid.Column="0"
Margin="5"
HorizontalAlignment="Right"
Command="{Binding Path=SubmitComment1Command}"
CommandParameter="{Binding ElementName=textBox,
Path=Text}"
Content="Submit1" />
</StackPanel>
<Button x:Name="SubmitButton2"
Grid.Column="1"
Margin="5"
HorizontalAlignment="Right"
Command="{Binding Path=SubmitComment2Command}"
Content="Submit2" />
</Grid>
</Window>
然后一切都会正常工作。要让您更详细地了解MVVM和RelayCommand:
您不必在Xaml中声明ViewModel,这主要是在应用程序根级别以编程方式完成的,可能需要一些DI
当坚持这一点时,您的RelayCommand应如下所示:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#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 // Constructors
#region ICommand Members
[DebuggerStepThrough]
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 // ICommand Members
}
public class GenericRelayCommand<T> : ICommand
{
private readonly Action<T> _execute;
public Predicate<T> CanExecuteFunc { get; private set; }
public GenericRelayCommand(Action<T> execute) : this(execute, p => true)
{}
public GenericRelayCommand(Action<T> execute, Predicate<T> canExecuteFunc)
{
_execute = execute;
CanExecuteFunc = canExecuteFunc;
}
public bool CanExecute(object parameter)
{
var canExecute = CanExecuteFunc((T)parameter);
return canExecute;
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Orientation="Horizontal">
<TextBox Name="textBox"
Width="200"
Text="{Binding Comment,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<Button x:Name="SubmitButton1"
Grid.Column="0"
Margin="5"
HorizontalAlignment="Right"
Command="{Binding Path=SubmitComment1Command}"
CommandParameter="{Binding ElementName=textBox,
Path=Text}"
Content="Submit1" />
</StackPanel>
<Button x:Name="SubmitButton2"
Grid.Column="1"
Margin="5"
HorizontalAlignment="Right"
Command="{Binding Path=SubmitComment2Command}"
Content="Submit2" />
</Grid>
</Window>
然后一切都会正常工作。代码中没有任何错误。。检查是否正确应用了Datacontext。。添加另一个文本属性并将其绑定到textblock并检查是否显示?使用Snoop()在运行时检查datacontext在我看来,您没有发送命令参数,在RelayCommand实现中,由于某种原因,只有在参数不为null时才调用execute。为什么在ViewModel.cs中使用ICommand而不是RelayCommand?代码中没有任何错误。。检查是否正确应用了Datacontext。。添加另一个文本属性并将其绑定到textblock并检查是否显示?使用Snoop()在运行时检查datacontext在我看来,您没有发送命令参数,在您的RelayCommand实现中,由于某些原因,只有在参数不为null时才调用execute。为什么在ViewModel.cs中使用ICommand而不是RelayCommand?感谢所有响应者。这个特殊的解决方案对我有效。@user3317801如果这个解决方案对你有效,那么请将它标记为一个答案,以帮助其他人注意到它。我想我说得太早了。我在下午早些时候尝试了这个解决方案,并认为它是成功的,因为在启动外接程序时,调用了SubmitCommentCommand,但今晚当我尝试重新启动应用程序时,我注意到该命令除了在启动时外,没有其他时间执行。我猜它总是这样,我从来没有注意到。不管怎样,我不知道这里发生了什么。我将按照另一位对此问题发表评论的人的建议尝试下载snoop,看看会发生什么。@user3317801您应该给GalaSoft一次尝试,它是针对MVVM模式的,我用它测试了我的解决方案。只是想让您知道,我认为您的解决方案可以工作,但我注意到Visual Studio中的XAML编辑器给了我一个警告。这可能是我的问题的根源:基本上,当我在UserControl.Resources标记中命名视图模型时,即警告说“ViewModel不存在于名称空间clr-…”中。你认为有什么办法可以避免这种情况吗?我知道ViewModel存在并编译。不知道为什么XAML不能识别它。我声明通过说出up-top-xmlns:local=“clr namespace:AppName”来进行本地声明,因为它位于目录的顶层。感谢所有响应者。这个特殊的解决方案对我有效。@user3317801如果这个解决方案对你有效,那么请将它标记为一个答案,以帮助其他人注意到它。我想我说得太早了。我在下午早些时候尝试了这个解决方案,并认为它是成功的,因为在启动外接程序时,调用了SubmitCommentCommand,但今晚当我尝试重新启动应用程序时,我注意到该命令除了在启动时外,没有其他时间执行。我猜它总是这样,我从来没有注意到。不管怎样,我不知道这里发生了什么。我将按照另一位对此问题发表评论的人的建议尝试下载snoop,看看会发生什么。@user3317801您应该给GalaSoft一次尝试,它是针对MVVM模式的,我用它测试了我的解决方案。只是想让您知道,我认为您的解决方案可以工作,但我注意到Visual Studio中的XAML编辑器给了我一个警告。这可能是
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}