Re-evaluating CanExecute on property change - c#

I am trying to implement ICommandSource on a custom control (similar to a button). Currently the implementation is mostly like it is displayed on the msdn page for ICommandSource and as it shows in the ButtonBase source code.
CanExecute fires on load of the control but doesn't fire when any property has changed. The same command being passed to a regular button works just fine. When the property that is supposed to change changes, CanExecute fires and the button is enabled. The command is a Delegate Command.
I have tried CommandManager.InvalidateRequerySuggested(); but that has not worked.
Any ideas?
Here's the implementation in the custom control:
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CollapsibleSplitButton csb = (CollapsibleSplitButton)d;
csb.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
}
private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null) UnhookCommand(oldCommand);
if (newCommand != null) HookCommand(newCommand);
}
private void UnhookCommand(ICommand command)
{
command.CanExecuteChanged -= OnCanExecuteChanged;
UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
command.CanExecuteChanged += OnCanExecuteChanged;
UpdateCanExecute();
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
UpdateCanExecute();
}
private void UpdateCanExecute()
{
if (Command != null)
CanExecute = Command.CanExecute(CommandParameter);
else
CanExecute = true;
}
protected override bool IsEnabledCore
{
get { return base.IsEnabledCore && CanExecute; }
}
Where I setup the Command I have:
...
MyCommand = new DelegatingCommand(DoStuff, CanDoStuff);
...
private bool CanDoStuff()
{
return (DueDate == null);
}
private void DoStuff() {//do stuff}

With delegate commands, you have to raise the CanExecuteChanged explicitly whenever you think it should be updated on UI. Try using this version of command called RelayCommand -
public class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command.
///This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current
///state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require
/// data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require
///data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
And register like Delegate commands in your class-
public ICommand TestCommand { get; private set; }
TestCommand = new RelayCommand<object>(CommandMethod, CanExecuteCommand);
EDIT
Try putting CommandManager.InvalidateRequerySuggested(); in your CanExecute -
private void OnCanExecuteChanged(object sender, EventArgs e)
{
CommandManager.InvalidateRequerySuggested();
UpdateCanExecute();
}

Managed to resolve the issue by wrapping the callback in an EventHandler.
private EventHandler currentHandler;
private void UnhookCommand(ICommand command)
{
if (currentHandler != null)
command.CanExecuteChanged -= currentHandler;
UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
if (currentHandler == null) return;
command.CanExecuteChanged += currentHandler;
UpdateCanExecute();
}

Related

Set up button's IsEnabled property with ICommand [duplicate]

This question already has answers here:
WPF MVVM command canexecute enable/disable button
(4 answers)
Disable button in WPF?
(5 answers)
How does one "disable" a button in WPF using the MVVM pattern?
(5 answers)
Command source disabling and enabling
(1 answer)
Closed 5 years ago.
I have the command
public class RelayActionCommand : ICommand
{
/// <summary>
/// The Action Delegate representing a method with input parameter
/// </summary>
public Action<object> ExecuteAction { get; set; }
/// <summary>
/// The Delegate, used to represent the method which defines criteria for the execution
/// </summary>
public Predicate<object> CanExecuteAction { get; set; }
public bool CanExecute(object parameter)
{
if (CanExecuteAction != null)
{
return CanExecuteAction(parameter);
}
return true;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
if (ExecuteAction != null)
{
ExecuteAction(parameter);
}
}
}
To use it,
public RelayActionCommand SearchPersonCommnad { get; set; }
DataAccess objds;
public PersonViewModel()
{
Persons = new ObservableCollection<PersonInfo>();
objds = new DataAccess();
Persons = new ObservableCollection<PersonInfo>(objds.GetPersonData());
var defaultView = CollectionViewSource.GetDefaultView(Persons);
//based upon the data entered in the TextBox
SearchPersonCommnad = new RelayActionCommand()
{
CanExecuteAction = n=> !String.IsNullOrEmpty(Name),
ExecuteAction = n => defaultView.Filter = name => ((PersonInfo)name).FirstName.StartsWith(Name)
|| ((PersonInfo)name).LastName.StartsWith(Name)
|| ((PersonInfo)name).City==Name
};
At the beginning, the button is disabled. But in running time, it changes by different situations. My question is how to set up the button's IsEnabled property with it? Which means, when ExecuteAction I have to set up the property correctly.
UPDATE:
I use ICommand not DelegateCommand.
You can use the CanExecute method, but it is good practice is actually to avoid this, and bind the button's enabled state to a separate boolean property of the view model. Most other solutions will have unexpected effects, or be suboptimal. Why?
CanExecute is a method. This means that it needs to be polled for the button state to change. You can force the control that's using the command to re-poll on a status change, but the code is much cleaner and more straightforward if you just use a property on the view model. This is because as a method, you can't use INotifyPropertyChanged to notify for changes, whereas with a property you can.
The danger in using CanExecute is that the user will manage to click the button after the method would return false, but before the button's enablement has changed.
Edit: Code to do what you want:
public class ViewModel : INotifyPropertyChanged
{
private int someValue;
private bool isEnabled;
public ViewModel()
{
MyCommand = new RelayActionCommand(Click);
}
private void Click(object obj)
{
//Do something.
}
/// <summary>
/// Bind this to the IsEnabled property of the button, and
/// also the background using a convertor or see ButtonBackground.
/// </summary>
public bool IsEnabled => SomeValue < 5;
/// <summary>
/// Option 2 - use this property to bind to the background of the button.
/// </summary>
public Brush ButtonBackground => IsEnabled ? Brushes.SeaShell : Brushes.AntiqueWhite;
public int SomeValue
{
get { return someValue; }
set
{
if (value == someValue) return;
someValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(ButtonBackground));
}
}
/// <summary>
/// Bind this to the command of the button.
/// </summary>
public RelayActionCommand MyCommand { get; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged
([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Relay command fixed up a bit to avoid using CanExecute:
public class RelayActionCommand : ICommand
{
public RelayActionCommand(Action<object> executeAction)
{
ExecuteAction = executeAction;
}
/// <summary>
/// The Action Delegate representing a method with input parameter
/// </summary>
public Action<object> ExecuteAction { get; }
/// <summary>
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
ExecuteAction?.Invoke(parameter);
}
//Deliberately empty.
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
}
EDIT 2: Code to do what you want using a DelegateCommand
Note, this does not use InvalidateRequerySuggested - mainly because it refreshes all buttons when any CanExecute changes, which is a poor solution. As you can see, this is less immediately straightforward than putting the code in the view model directly, but whatever floats your boat I guess.
public sealed class ViewModel : INotifyPropertyChanged
{
private int calls;
public ViewModel()
{
SafeOnceCommand = new RelayCommand(DoItOnce, HasDoneIt);
}
private bool HasDoneIt()
{
return Calls == 0;
}
private void DoItOnce()
{
if (Calls > 0) throw new InvalidOperationException();
Calls++;
}
public int Calls
{
get { return calls; }
set
{
if (value == calls) return;
calls = value;
OnPropertyChanged();
SafeOnceCommand.RaiseCanExecuteChanged();
}
}
public RelayCommand SafeOnceCommand { get; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public sealed class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
private readonly List<EventHandler> invocationList = new List<EventHandler>();
public RelayCommand(Action execute, Func<bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute();
}
public void Execute(object parameter)
{
execute();
}
/// <summary>
/// Method to raise CanExecuteChanged event
/// </summary>
public void RaiseCanExecuteChanged()
{
foreach (var elem in invocationList)
{
elem(null, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged
{
add { invocationList.Add(value); }
remove { invocationList.Remove(value); }
}
}

detect which button was clicked from ViewModel WPF

there are many buttons on the Main window of my WPF-App.
The commands of those buttons should have the same implementation/function but depending on which button has been pressed, the file/path on which the function accesses changes.
How to detect which button was clicked from ViewModel without using button click event handler (Windows forms)?
Here is the implementation of class RelayCommand:
public class RelayCommand : ICommand
{
readonly Func<Boolean> _canExecute;
readonly Action _execute;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<Boolean> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public Boolean CanExecute(Object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(Object parameter)
{
_execute();
}
}
Here is the code of the command in ViewModel:
void DoThisWorkExecute()
{
// if Button1 is clicked...do this
// if Button2 is clicked...do this
}
bool CanDoThisWorkExecute()
{
return true;
}
public ICommand ButtonCommand { get { return new RelayCommand(DoThisWorkExecute, CanDoThisWorkExecute); } }
You can use the CommandParameter. Something like that:
<Button Content="Open" Command="{Binding Path=ButtonCommand}" CommandParameter="Open"/>
<Button Content="Save" Command="{Binding Path=ButtonCommand}" CommandParameter="Save"/>
For this you need a slightly different implementation of the RelayCommand
/// <summary>
/// https://gist.github.com/schuster-rainer/2648922
/// Implementation from Josh Smith of the RelayCommand
/// </summary>
public class RelayCommand : ICommand
{
#region Fields
readonly Predicate<object> _canExecute;
readonly Action<object> _execute;
#endregion // Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand"/> class.
/// </summary>
/// <param name="execute">The execute.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand"/> class.
/// </summary>
/// <param name="execute">The execute.</param>
/// <param name="canExecute">The can execute.</param>
/// <exception cref="System.ArgumentNullException">execute</exception>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
However: Instead of asking which button was clicked, I would make a Command for each separate action (e.g. open, save, exit). You will have much less troubles when reusing your commands (context menu, KeyBindings, toolbar, etc.). You would always have to provide the ui element. This really breaks the MVVM pattern. You really have to get rid of the old winforms approach, in order to use the full power of the RelayCommand.
I wrote myself a code snippet so I don't have to write all the code.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>RelayCommand</Title>
<Shortcut>RelayCommand</Shortcut>
<Description>Code snippet for usage of the Relay Command pattern</Description>
<Author>Mat</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>name</ID>
<ToolTip>Name of the command</ToolTip>
<Default>Save</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[ private RelayCommand _$name$Command;
public ICommand $name$Command
{
get
{
if (_$name$Command == null)
{
_$name$Command = new RelayCommand(param => this.$name$(param),
param => this.Can$name$(param));
}
return _$name$Command;
}
}
private bool Can$name$(object param)
{
return true;
}
private void $name$(object param)
{
MessageServiceHelper.RegisterMessage(new NotImplementedException());
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
see also https://msdn.microsoft.com/en-us/library/z41h7fat.aspx

Button command class to take a parameter

Using c# + wpf + mvvm I am trying to make a more or less generic "buttoncommand" class following level 4 at http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level
I have a datagrid thats bound to observablecollection<mySpecialClass> and a button bound a command that adds row and takes no parameters that works fine.
However I would like to have buttons to insert and remove rows in the grid, that would take the index of the row that is currently active/selected.
I have tried to change the buttoncommand to the following (changing Action what to Action<object> what):
public class ButtonCommandi : ICommand
{
private Action<object> _whattoExecute;
private Func<bool> _whentoExecute;
public ButtonCommandi(Action<object> what, Func<bool> when)
{
_whattoExecute = what;
_whentoExecute = when;
}
public bool CanExecute(object parameter)
{
return _whentoExecute();
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_whattoExecute(parameter);
}
}
}
However, in my viewmodel, as I try to create instances of the class in the constructor:
public class MyViewModelClass
{
private ButtonCommand _objAppendTerrainPointCommand;
private ButtonCommandi _objInsertTerrainPointCommand;
private MyModelClass _mymodel;
public MyVeiwModelClass()
{
...
_objAppendRowCommand = new ButtonCommand(_mymodel.Append, _mymodel.IsPossibleToAppend);
_objInsertRowCommand= new ButtonCommandi(
delegate(object i) { _mymodel.InsertRow(i); }, _mymodel.IsPossibleToInsert);
...
}
it says that "the best overloaded method match for 'MyModelClass.InsertRow(int)' has some invalid arguments". I have tried some different versions of the new ButtonCommandi(..) but cannot seem to find the way.
in MyModelClass the function looks like this:
internal void InsertRow(int idx)
{
_myObsColSpecial.Insert(idx);
}
Does anyone have a good hint how to have this work? (I am new to the wpf, mvvm and c# so bear with me. As far as I understand there seems to be a lot of ways to accomplish something like this but since I started down this way, it would be nice not to have to rewrite a "ton" of code :) )
For RelayCommand that passes an object try this....
class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
In your View Model...
class MainWindowVM
{
public RelayCommand<string> WindowCommand { get; set; }
public MainWindowVM()
{
WindowCommand = new RelayCommand<string>(OnWindowCommand);
}
private void OnWindowCommand(string obj)
{
// obj is the string passed from the Button CommandParameter
}
}
In your XAML
<Window.DataContext>
<local:MainWindowVM/>
</Window.DataContext>
<Grid>
<Button Command="{Binding WindowCommand}" CommandParameter="Test" />
</Grid>

Universal Windows WPF CommandParameter bind to static Enumeration

I need help on 2 things.
sending parameters (which is a static Enum) from a view to the viewmodel (I know I must use the CommandParameter on my button).
How to delcare my DelegateCommand class so that it can accept the parameter.
Enumeration :
public static class Helpers
{
public enum Operations
{
ONE,
TWO
}
}
ViewModel
public class SettingViewModel : ViewModelBase
{
private DelegateCommand _UpdateCommand;
public ICommand UpdateOperationValue
{
get
{
if (_UpdateCommand== null)
_UpdateCommand= new DelegateCommand(Of Helpers.Operations)(param => UpdatePaint()); // Gives me erreur
return _UpdateCommand;
}
}
}
View:
<Button Height="100" Width="100" Content="PEINTURE"
Background="{Binding PaintColorBrush}"
Command="{Binding UpdateOperationValue}"
CommandParameter="[... What do I do here ? ...]"/>
I've been searching on the web for solutions and came accross this :
<Button CommandParameter="{x:Static local:SearchPageType.First}" .../>
sadly in Universal Windows app I don't have the x:Static
My DelegateCommand class :
using System;
using System.Windows.Input;
public class DelegateCommand : ICommand
{
/// <summary>
/// Action to be performed when this command is executed
/// </summary>
private Action<object> _executionAction;
/// <summary>
/// Predicate to determine if the command is valid for execution
/// </summary>
private Predicate<object> _canExecutePredicate;
/// <summary>
/// CanExecuteChanged event handler
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// Initialize a new instance of the clDelegateCommand class
/// The command will always be valid for execution
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{ }
/// <summary>
/// Initializes a new instance of the clDelegateCommand class
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
/// <param name="canExecute">The predicate to determine if the command is valid for execution</param>
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this._executionAction = execute;
this._canExecutePredicate = canExecute;
}
/// <summary>
/// Raised when CanExecute is changed
/// </summary>
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
/// <summary>
/// Execute the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter"></param>
/// <returns>True if command is valid for execution</returns>
public bool CanExecute(object parameter)
{
return this._canExecutePredicate == null ? true : this._canExecutePredicate(parameter);
}
/// <summary>
/// Execute the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to delegate</param>
/// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
public void Execute(object parameter)
{
if (!CanExecute(parameter))
{
throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
}
this._executionAction(parameter);
}
}
How can I send a enum parameter from my view to my view model
How can I instanciate a new DelegateCommand and receiving a enum as parameters.
How to delcare my DelegateCommand class so that it can accept the parameter.
You can use below class to accept parameters,
public class DelegateCommand: ICommand
{
#region Constructors
public DelegateCommand(Action<object> execute)
: this(execute, null) { }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute != null ? _canExecute(parameter) : true;
}
public void Execute(object parameter)
{
if (_execute != null)
_execute(parameter);
}
public void OnCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#endregion
private readonly Action<object> _execute = null;
private readonly Predicate<object> _canExecute = null;
}
In ViewModel ICommand Property example below,
public ICommand ExitCommand
{
get
{
if (exitCommand == null)
{
exitCommand = new DelegateCommand((obj)=>CloseApplication());
}
return exitCommand;
}
}
How can I send a enum parameter from my view to my view model
Commandparameter accept object. Bind your enum to CommandParameter and cast it in your ViewModel

Button command binding doesn't work

I created a new UserContol with a button inside. Iwanted to bind the button command to a dependancy property of the new user control like this.
<Grid>
<Button Name="Button1" Command="{Binding Button1Command}" />
</Grid>
this is the DP on the containing UserControl:
public ICommand Button1Command
{
get { return (ICommand)GetValue(Button1CommandProperty); }
set { SetValue(Button1CommandProperty, value); }
}
public static readonly DependencyProperty Button1CommandProperty =
DependencyProperty.Register("Button1Command", typeof(ICommand), typeof(BptCellTemplate), new FrameworkPropertyMetadata(null));
when i try to use it nothing happen when I press the button. It doesn't recognize the command. If I add an event it works. Like this:
public static readonly DependencyProperty Button1CommandProperty =
DependencyProperty.Register("Button1Command", typeof(ICommand), typeof(BptCellTemplate), new FrameworkPropertyMetadata(null, OnButton1CommandChanged));
private static void OnButton1CommandChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
var bptCellTemplate = dependencyObject as BptCellTemplate;
if (bptCellTemplate == null || !(args.NewValue is ICommand))
{
return;
}
(bptCellTemplate.DataContext as BptCellTemplateViewModel).Button1Command = (ICommand)args.NewValue;
}
Is there a way to bind it without an event? because it works with other button properties that i did the same way (Visibility for example)
It's possible that your binding is not working because there is nothing that says the Button1Command property is a member of your UserControl.
You can confirm that this is the problem by looking in the Output window when debugging your program in Visual Studio. You'll likely see binding errors that member Button1Command wasn't found.
The typical fix for this is to add a name attribute to your UserControl's root element, such as x:Name="root" (you can choose your own name or use an existing one if you have it). Then, change your binding to the command to reference the new name:
<Button Name="Button1" Command="{Binding Button1Command, ElementName=root}" />
You need class implements ICommand interface.
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
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
}
Now there is binding very simple.
Define Command in your DataContext (MVVM ...ect.)
Don't remember setup DataContext ... for example DataContext = this; (this is your Window)
RelayCommand _btnCommand;
public ICommand Button1Command
{
get
{
if (_btnCommand == null)
{
_btnCommand = new RelayCommand(param => this.ExecuteButton1(),
param => this.CanButton1());
}
return _btnCommand;
}
}
public void ExecuteButton1()
{
}
public bool CanButton1()
{
return true;
}
That's it ...

Categories