Reputation: 171
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.
For that case I use a RelayCommmand
. The RelayCommand
is a standard class you find on Internet and will be shown in the end.
To organise the command I wrote a class called 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:
<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:
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
. 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
:
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);
}
}
Upvotes: 0
Views: 2677
Reputation: 2936
I strongly recommend using existing frameworks, instead of inveting the wheel once again. Take a look at 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.
You can easily add another condition for disabling the command, and then, binding will disable button
Upvotes: 0
Reputation: 169240
The
RelayCommand
is a standard class you find on 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".
A good implementation should contain a method for raising the CanExecuteChanged
event. MvvmLight's implementation has a RaiseCanExecuteChanged()
method that does this. 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.
Edit: Your implementation doesn't have any RaiseCanExecuteChanged()
method. Add one to your RelayCommand
class and call it as per above:
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
Upvotes: 1