[英]The RelayCommand for enable/disable a button don't work like expected
The case is that I try to disable a button in the window form when it was clicked and after some time (some seconds) it should be enabled again. 这种情况是,我尝试在单击窗口表单中的按钮时将其禁用,并且在一段时间(几秒钟)后应再次启用它。
But this didn't work. 但这没有用。 After a click on the button the command set the enabled to
false
and after some seconds the command set it back to true
(I tested it, the order is right and it set it to true
again) but the button is still not enabled on the window form. 单击按钮后,该命令将启用设置为
false
,几秒钟后,该命令将其设置为true
(我测试了该命令,顺序是正确的,并且再次将其设置为true
),但是该按钮仍未启用窗口形式。
For that case I use a RelayCommmand
. 对于这种情况,我使用
RelayCommmand
。 The RelayCommand
is a standard class you find on Internet and will be shown in the end. RelayCommand
是您在Internet上找到的标准类,将在最后显示。 To organise the command I wrote a class called Testclass
: 为了组织命令,我编写了一个称为
Testclass
的类:
class Testclass
{
private bool _testValueCanExecute;
public bool TestValueCanExecute
{
get { return _testValueCanExecute; }
set
{
_testValueCanExecute = value;
OnPropertyChanged();
}
}
public ICommand TestValueCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public Testclass()
{
TestValueCommand = new RelayCommand(TestMethod, param => _testValueCanExecute);
TestValueCanExecute = true;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private async void TestMethod(object obj)
{
TestValueCanExecute = false;
await Task.Delay(3000);
TestValueCanExecute = true;
}
}
In the XAML File I added a button as followed: 在XAML文件中,我添加了一个按钮,如下所示:
<Button x:Name="TestButton" Command="{Binding TestValueCommand}" Content="Test Button" HorizontalAlignment="Left" Margin="149,96,0,0" VerticalAlignment="Top" Width="75"/>
The MainWindow
code looks as followed: MainWindow
代码如下所示:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Testclass();
}
}
So the RelayCommand
use the TestMethod
method set the command enable variable to false
, wait 3 seconds and set them back to true
. 因此,
RelayCommand
使用TestMethod
方法将命令enable变量设置为false
,等待3秒钟,然后将它们设置为true
。 But as I wrote above the button on the window form still not enabled. 但是,正如我在上方所述,窗口窗体上的按钮仍未启用。
It would be nice to understand what happens here and how I can solve this. 很高兴了解这里发生的事情以及如何解决此问题。
Update: I use the following Code for the RelayCommand
: 更新:我对
RelayCommand
使用以下代码:
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
The
RelayCommand
is a standard class you find on Internet ...RelayCommand
是您在Internet上找到的标准类...
There is no such thing as a "standard class you find on Internet". 没有“在互联网上找到的标准班级”这样的东西。 In fact there are several different implementations of the
RelayCommand
available "on the Internet". 实际上,“在Internet上”有几种不同的
RelayCommand
实现。
A good implementation should contain a method for raising the CanExecuteChanged
event. 一个好的实现应包含一个引发
CanExecuteChanged
事件的方法。 MvvmLight's implementation has a RaiseCanExecuteChanged()
method that does this. MvvmLight的实现具有执行此操作的
RaiseCanExecuteChanged()
方法。 You need to call this one to "refresh" the status of the command: 您需要调用此命令来“刷新”命令的状态:
private async void TestMethod(object obj)
{
RelayCommand cmd = TestValueCommand as RelayCommand;
TestValueCanExecute = false;
cmd.RaiseCanExecuteChanged();
await Task.Delay(3000);
TestValueCanExecute = true;
cmd.RaiseCanExecuteChanged();
}
The event is not raised automatically when you set the TestValueCanExecute
property and raise the PropertyChanged
event for the view model. 当您设置
TestValueCanExecute
属性并引发视图模型的PropertyChanged
事件时, 不会自动引发该事件。
Edit: Your implementation doesn't have any RaiseCanExecuteChanged()
method. 编辑:您的实现没有任何
RaiseCanExecuteChanged()
方法。 Add one to your RelayCommand
class and call it as per above: 将一个添加到您的
RelayCommand
类中,然后按上述方式调用它:
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
I strongly recommend using existing frameworks, instead of inveting the wheel once again. 我强烈建议您使用现有的框架,而不是再费周折。 Take a look at ReactiveUI ReactiveCommand
看看ReactiveUI ReactiveCommand
In your case, it would do all the work by itself: 在您的情况下,它将自行完成所有工作:
TestValueCommand = ReactiveCommand.CreateFromTask(async () => await Task.Delay(500));
You bind that command to a button in xaml and the button is disabled until command is done. 您将该命令绑定到xaml中的按钮,并且该按钮将被禁用,直到命令完成。
You can easily add another condition for disabling the command, and then, binding will disable button 您可以轻松地添加另一个条件来禁用该命令,然后绑定将禁用按钮
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.