this question is just for understanding. I'm fine with my IDE telling me about errors that aren't there, as long as the application works.
I'm developing a c# WPF application using the MVVM pattern; data and CommandBindings.
However, I've noticed that when I use a binding to bind to a Command, the command doesn't execute, however, I don't get any errors shown in either the IDE, or debug output.
For example:
Command="{Binding MyCommand}"
<!-- Or -->
Command="{Binding cmd:Commands.MyCommand}"
However, just writing
Command="cmd:Command.MyCommand"
works just fine, although the XAML-editor shows me an error, saying that the command cannot be found.
Why is this so?
You need to bind to a property of type ICommand.
This property will implement a RelayCommand with your function.
The default implementation of the RelayCommand is as follows:
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private readonly Action methodToExecute;
private readonly Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (canExecuteEvaluator == null)
{
return true;
}
bool result = canExecuteEvaluator.Invoke();
return result;
}
public void Execute(object parameter)
{
methodToExecute.Invoke();
}
}
In the ViewModel you need to implement the property of type ICommand with your OnClick-function:
public ICommand MyCommand
{
get
{
return new RelayCommand(() =>
{
doSomething();
});
}
}
Now you are able to bind the Button-Command of your view to the ICommand dynamically at runtime:
Command="{Binding MyCommand}"
Besides, keep in mind that Command="cmd:Command.MyCommand" is a static implementation.
Here is relayCommand that I use:
public sealed class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _action;
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion Fields
#region Constructors
public RelayCommand(Action<object> action)
{
if (action != null)
_action = action;
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion Constructors
#region ICommand Members
public void Execute(object parameter)
{
if (_execute != null)
_execute(parameter);
else
{
_action(parameter ?? "Command parameter is null!");
}
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
#endregion
}
What you need is to implement in viewModel command and you will be able to bind it like this:
Command="{Binding MyCommand}"
Edit
As for me, I prefer to use two libraries - interactions and Interactivity. With their help it is easy to bind all events to viewModel. For example:
xaml:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="OnClick"/>
</i:EventTrigger>
</i:Interaction.Triggers>
and viewModel:
public void OnClick(object sender, RoutedEventArgs e)
{
//your code
}
Related
!!! SOLVED, THANK YOU VERY MUCH !!!
I'm writing my first MVVM application (in WPF C#). Because of that, I want to use commands instead "Click" event defined in a view. The command, which I want to induce is really simple, it should to create and open a view.
I have written RelayCommand class which inherits ICommand interface.
internal class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
I write a method changing value of the field, which represent a view.
private bool openSoundsWindow;
private bool openChordsWindow;
public bool OpenSoundsWindow
{
get { return openSoundsWindow; }
set { openSoundsWindow = value; }
}
public bool OpenChordsWindow
{
get { return openChordsWindow; }
set { openChordsWindow = value; }
}
public void OpenSounds()
{
openSoundsWindow = true;
}
public void OpenChords()
{
OpenChordsWindow = true;
}
I wrote in view model class commands by RelayCommand and OnPropertyChanged event. View model class inherits INotifyPropertyChanged.
private MainModel model = new MainModel();
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public bool OpenSoundsWindow
{
get { return model.OpenSoundsWindow; }
set
{
model.OpenSoundsWindow = value;
OnPropertyChanged(nameof(OpenSoundsWindow));
}
}
private ICommand openSounds = null;
public ICommand OpenSounds
{
get
{
if (openSounds == null)
{
openChords = new RelayCommand(
(object o) =>
{
model.OpenSounds();
OnPropertyChanged(nameof(OpenSoundsWindow));
var newSoundsWindow = new Sounds();
newSoundsWindow.Show();
},
(object o) =>
{
return model.OpenSoundsWindow != null;
});
}
return openSounds;
}
}
I created instance of view model in view's xaml code.
xmlns:vm="clr-namespace:HearingTeacher.ViewModels"
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
<Window.Resources>
<vm:MainViewModel x:Key="mainViewModel" />
</Window.Resources>
I binded property command for buttons with created commands in view model.
<Button Grid.Row="0" Content="Sounds" Command="{Binding Path=OpenSounds,
UpdateSourceTrigger=PropertyChanged}" />
Compiler doesn't throw any exception, and .NET starts an application correctly, but commands doesn't work.
How to use 2 different commands for 2 different buttons in a viewmodel.
MY requirement is to use 2 buttons in my page.
I have implemented for 1 button , but not able to implement for multiple buttons .
Can anyone provide me a example of using multiple commands in viewmodel using MVVM.
I am very new to MVVM , so please help me out.
1) Create RelayCommand class:
public class RelayCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
this._canExecute = canExecute;
this._execute = execute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
2) Create ICommand properties in your VM:
public ICommand Command1 { get { return new RelayCommand(e => true, this.MethodForCommand1); } }
public ICommand Command2{ get { return new RelayCommand(e => true, this.MethodForCommand2); } }
private void MethodForCommand1(object obj){ //Type your code for Command1 }
private void MethodForCommand2(object obj){ //Type your code for Command2 }
3) Bind command in view:
<Button Content="Button 1" Command="{Binding Command1}"/>
<Button Content="Button 2" Command="{Binding Command2}"/>
Hope it's help ;)
I'm still learning about wpf, however I'm familiar withe how to setup mvvm in wpf c#. However when it comes to the ICommand/RelayCommand stuff, its a bit of a confusing area for me. Over the past few months I've compiled a few implementations of the ICommand classes in order to create my tools. However I'm at the point now where I've read a few articles and I've looked at the code long enough, I'm looking for someone to help me out and put into simple terms what is going on here and if so, how can I combine/clean up these classes. At the moment the code seems redundant and I'm not sure how to go about optimizing it. Hope this isn't asking for to much. Thanks.
The two important things I want to maintain in this, is the ability to pass arguments to the commands as seen in this first usage example of RelayCommand. Secondly the ability to enable/disable a command as seen in the second command.
So in my tool i have this helper class.
1. I don't get the differences of use between the two classes inside this RelayCommand.cs. There is a public and an internal class.
2. Is there a need for both or can they be combine?
RelayCommand.cs
using System;
using System.Windows.Input;
namespace WpfApplication1.Helper
{
public class RelayCommand<T> : ICommand
{
private readonly Action<T> execute;
private readonly Predicate<T> canExecute;
public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (parameter == null)
{
return true;
}
else
{
return canExecute == null || canExecute((T)parameter);
}
}
public void Execute(object parameter)
{
execute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
// added
internal class RelayCommand : ICommand
{
private readonly Predicate<object> canExecute;
private readonly Action<object> execute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
An example of me using the RelayCommand.cs in my class object called Customer.cs
private ICommand addNewLicense_Command;
public ICommand AddNewLicense_Command
{
get
{
return addNewLicense_Command ?? (addNewLicense_Command = new RelayCommand<Customer>(n =>
{
AddNewLicense_Execute(n);
}));
}
}
So then in my MainViewModel.cs i have another ICommand Class in the same project my Helper class mentioned above is part of. Is this class necessary? It seems so similar to the RelayCommand class.
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
An example of me using CommandHandler in my MainViewModel.cs
private ICommand addNewUser_Command;
public ICommand AddNewUser_Command
{
get
{
return addNewUser_Command ?? (addNewUser_Command = new CommandHandler(() => AddNewUser_Execute(), true));
}
}
If you use a library like MVVM Lite then it will provide the RelayCommand implementations for you. Either way use the non-generic when you don't need a parameter passed in e.g. an "Ok" button:
public ICommand OkCommand { get { return new RelayCommand(Ok); } }
protected virtual void Ok()
{
// ... do something ...
}
The associated XAML is something like:
<Button Content="Ok" Command="{Binding OkCommand}" IsDefault="True" />
Use the generic when you want to pass a parameter:
public ICommand OpenClientCommand { get { return new RelayCommand<Client>(OnOpenClient); } }
private void OnOpenClient(Client client)
{
// ... do something with client ...
}
In this case you need to pass in a Client object via the command parameter:
<Button Content="Open" Command="{Binding OpenClientCommand}" CommandParameter="{Binding SelectedClient}"/>
Passing parameters is also handy when used with event triggers, e.g. you can add something like this to intercept your MainWindow's Closing event:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding ClosingCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
This trigger passes the message arguments into your handler which gives you the opportunity to cancel it in the event that the user hasn't saved their changes:
public ICommand ClosingCommand { get { return new RelayCommand<CancelEventArgs>(OnClosing); } }
private void OnClosing(CancelEventArgs args)
{
if (!PromptUserForClose())
args.Cancel = true;
}
The RelayCommand you have is all you need. If you want to disable the command you can pass a method in the constructor do do so:
return addNewLicense_Command ?? (addNewLicense_Command = new RelayCommand<Customer>(n =>
{
AddNewLicense_Execute(n);
},AllowAddNeLicense));
...
bool AllowAddNewLicense()
{
return _allowAddEnabled;
}
The second class called CommandHandler is just another implementation of ICommand. The difference is that you can pass the "enabled" boolean inside the constructor, which means it will remain the same unless you create a new instance of it. While in the RelayCommand you can pass a function that gets executed everytime* so you can influence the outcome.
I am new to C# and I need to create simple binding command for one button. I have been reading a lot of articles for last hours but it simply got me more confused.
I have an WPF window (let's say Window1) where I have button "AddCustomer". What is the simplest way to create command for it? (By simplest I mean easy to understand)
In every article they were doing it differently. I need you to show me also how to bind it in xaml, more detailed the better... like I said, I am new.
Thank you for your help.
below is the complete solution for commands in WPF.
first create a class for execute the command.
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
private Action<object> _action;
private bool _canSave;
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;
}
public RelayCommand(Action<object> action, bool CanSave)
{
this._action = action;
this._canSave = CanSave;
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
below is the ViewModel
public FilterViewModel()
{
private RelayCommand _commandSave;
public ICommand Save
{
get {
return _commandSave ?? (_commandSave =
new RelayCommand(param => SaveMethod(param), CanSave));
}
}
private void SaveMethod
{
//code for save
}
private Predicate<object> CanSave
{
get { return o => true; }
}
}
and finally using the command in XAML.
<Button x:Name="btnSave" Content="Save" Command="{Binding Save}" CommandParameter="PASS-PARAMETER-HERE" ></Button>
Here's my take on it, the following is 'simplest' because you are leveraging the Prism library and so the amount of code you write is small. Use the nuget manager to add Prism to your project if you're not already using it ...
The xaml:
<Button Command="{Binding AddCustomerCommand}" Content="Add Customer"/>
In your viewmodel:
(1) Declare your command:
public ICommand AddCustomerCommand{ get; private set; }
(2) Define your command:
AddCustomerCommand= new DelegateCommand(AddCustomer);
(3) And create the method:
private void AddCustomer()
{
//do your logic here
}
Extended version:
You can pass a parameter from the xaml:
<Button Command="{Binding AddCustomerCommand}" CommandParameter={Binding SelectedItem, ElementName=MySelectorThingy} Content="Add Customer"/>
Remember to change the signature of your delegate and method:
AddCustomerCommand= new DelegateCommand<WhateverMyTypeIs>(AddCustomer);
private void AddCustomer(WhateverMyTypeIs selectedThing)
{
//do your logic here
}
You can also define in the DelegateCommand when the button should be available (CanExecute), like the following:
public DelegateCommand AddCustomerCommand{ get; private set; }
AddCustomerCommand = new DelegateCommand(AddCustomer, AddCustomer_CanExecute);
And then define the method for deciding whether you can execute or not:
private bool AddCustomer_CanExecute()
{
if (DateTime.Now.DayOfWeek.Equals(DayOfWeek.Monday))
return true;
else
return false;
}
I try to use commands with the MVVM - Pattern and I don't know how to "bind" a command to a special event, e.g. MouseUp or MouseEnter. How to do this?
First you should define ICommnad property in your ViewModel.
public ICommand MouseUpCommand
{
get
{
if (this.mouseUpCommand == null)
{
this.mouseUpCommand = new RelayCommand(this.OnMouseUp);
}
return this.mouseUpCommand;
}
}
private void OnMouseUp()
{
// Handle MouseUp event.
}
You can find lot of ICommand implementations. One of them:
public class RelayCommand : ICommand
{
public RelayCommand(Action<object> execute)
{
this._execute = execute;
...
}
...
public void Execute(object parameter)
{
_execute(parameter);
}
}
Then add event trigger within which invoke your Command:
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding MouseUpCommand}"/>
</i:EventTrigger>
Read the EventToCommand at the following page, please
Look at WPF Binding UI events to commands in ViewModel.
For this you need System.Windows.Interactivity.dll which you can get from Nuget
Completing #AnatoliiG post here's an implementation and a sample usage of the RelayCommand class.
Code:
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
}
Usage:
// To use this class within your viewmodel class:
RelayCommand _myCommand;
public ICommand MyCommand
{
get
{
if (_myCommand == null)
{
_myCommand = new RelayCommand(p => this.DoMyCommand(p),
p => this.CanDoMyCommand(p) );
}
return _myCommand;
}
}