I have the following code and it won't compile because the compiler cannot determine the return type of my CanExecute method. Can someone help me as to what is wrong?
class ViewCommand : ICommand
{
#region ICommand Members
public delegate Predicate<object> _canExecute(object param);
private ICommand _Execute;
_canExecute exe;
public bool CanExecute(object parameter)
{
return exe == null ? true : exe(parameter); // <-- Error no implicit conversion between Predicate<object> and bool
}
... // more code
}
The ICommand interface declares CanExecute as a function that takes a parameter and returns a bool.
Your _canExecute takes a parameter and returns a Predicate<object>
The way to invoke that would be to pass the parameter to the return value of exe
exe(parameter)(parameter);
I doubt that was your intention though.
I think you want to declare exe as a Predicate, and skip the delegate declaration.
private Predicate<object> exe;
This is what I think you want to look like:
class ViewCommand : ICommand
{
#region ICommand Members
private ICommand _Execute;
Predicate<object> exe;
public bool CanExecute(object parameter)
{
return exe == null ? true : exe(parameter); // <-- Error no implicit conversion between Predicate<object> and bool
}
... // more code
}
Related
So I have this View:
<StackPanel>
<TextBox x:Name="Name"/>
<Button x:Name="SayHello"
Content="Click Me" />
</StackPanel>
And I have this ViewModel:
internal class ShellViewModel : PropertyChangedBase
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyOfPropertyChange(() => Name);
NotifyOfPropertyChange(() => CanSayHello());
}
}
public bool CanSayHello()
{
bool isenabled = !string.IsNullOrWhiteSpace(Name);
return isenabled;
}
public void SayHello()
{
MessageBox.Show(string.Format("Hello, {0}!", Name));
}
}
But whenever I enter some value in the textbox, I got this exception:
{"Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.MemberExpression'."}
In the commercial app that I'm developing I must have the CanSayHello() member in the VM as a method, not as a property. What should I do?
You have that exception because you are calling NotifyOfPropertyChange on CanSayHello and CanSayHello is a method, not a property.
Change to:
public bool CanSayHello
{
get { return !string.IsNullOrWhiteSpace(Name); }
}
You should use commands to bind actions to UI items. There is an implementation of ICommand called RelayCommand which is typically used in most WPF projects. It allows you to use method, property or predicate.
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
_execute = execute;
_canExecute = canExecute;
}
[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);
}
}
Problem: Buttons never gets enabled.
<Button Name="btnCompareAxises"Command="{Binding CompareCommand}"
Content="{Binding VM.CompareAxisButtonLabel}"
IsEnabled="{Binding VM.IsCompareButtonEnabled}">
</Button>
ViewModel constructor:
this.CompareCommand = new DelegateCommand(CompareCommand, ValidateCompareCommand);
The problem seems to be related to the CanExecute eventhandler of the registered Command of the button.
The CanExecute handler returns false when the application loads.
This is fine, as the conditions are not met initially.
The canExecute handler only runs on application startup or when the button is clicked. You cannot click a disabled button, so the button stays disabled forever if the initial value returned form the CanExecute handler is false!
Question:
Do I have to enable the button again, only using the command bound to it.
Something like, hey command please reevaluate if the conditions for this buttons are met ?
Why sits the IsEnabled property under section Coercion and not under local?
The command:
public class DelegateCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> execute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
public void RaiseCanExecuteChanged()
{
this.OnCanExecuteChanged();
}
protected virtual void OnCanExecuteChanged()
{
var handler = this.CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Solved:
I had to adapt the DelegateCommand class to make it work:
I have added CommandManager.RequerySuggested to the public CanExecuteChanged Event property.
Now it will automatically re-evaluate the CanExecute method of the command when soemthing changes in the UI!
public class DelegateCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> execute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
/// CommandManager
/// Go to the "References" part of your class library and select "Add Reference".
/// Look for an assembly called "PresentationCore" and add it.
public event EventHandler CanExecuteChanged
{
add
{
_internalCanExecuteChanged += value;
CommandManager.RequerySuggested += value;
}
remove
{
_internalCanExecuteChanged -= value;
CommandManager.RequerySuggested -= value;
}
}
event EventHandler _internalCanExecuteChanged;
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
public void RaiseCanExecuteChanged()
{
this.OnCanExecuteChanged();
}
protected virtual void OnCanExecuteChanged()
{
var handler = this._internalCanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Removed this from the button:
IsEnabled="{Binding VM.IsCompareButtonEnabled}"
The binding here is not necessary, as the CanExecute handler will take care of the enabled/disabled state of the button!
I have two radio button.I just want to capture the selected radio button value in viewmodel.I have defined a method GetLOB() in which I want to capture the commandParameter value.
Here is my code
<RadioButton GroupName="Os" Content="Payroll" IsChecked="{Binding ObjEntrySheetManagerViewModel.CheckedProperty}" Command="LobType" CommandParameter="Payroll" Grid.Row="4" Grid.Column="0" Margin="25,15,0,0"/>
<RadioButton GroupName="Os" Content="Sales" Grid.Row="4" Grid.Column="1" Command="LobType" CommandParameter="Payroll" Margin="5,15,0,0"/>
private RelayCommand _LobType;
public ICommand LobType
{
get
{
if (_LobType == default(RelayCommand))
{
_LobType = new RelayCommand(GetLOB);
}
return _LobType;
}
}
private void GetLOB()
{
}
Capture parameter using lambda (assuming RelayCommand used by you have overloaded constructor which will take Action<object> as argument)
public ICommand LobType
{
get
{
if (_LobType == default(RelayCommand))
{
_LobType = new RelayCommand(param => GetLOB(param));
}
return _LobType;
}
}
private void GetLOB(object parameter)
{
}
Relay command sample from MSDN (in case you need):
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
#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
#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
}
I have 8 HyperlinkButton on my silverlight application.
I want to call method HyperlinkButtonClick_Event when each of them will be clicked.
Can i do it on style ?
If 'no' so how can i do it without adding the method explicitly on each of the HyperlinkButton instance ?
How about using something like this in your style:
<Setter Property="Command" Value="{Binding ClickCommand}" />
And using a Command, such as a DelegateCommand, with an Execute action replacing your HyperlinkButtonClick_Event code.
This is also obviously going to require you to have the datacontext set correctly for each of your buttons...
The DelegateCommand in it's VERY simplest form:
public class DelegateCommand : ICommand
{
private Func<object, bool> canExecute;
private Action<object> executeAction;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
this.executeAction = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this.executeAction(parameter);
}
public bool CanExecute(object parameter)
{
return this.canExecute(parameter);
}
}
You can find implementations of this everywhere, from SO to MSDN...
public class MyCheckBox : CheckBox
{
public MyCheckBox()
{
this.Click += new RoutedEventHandler(MyCheckBox_Click);
}
void MyCheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (sender as CheckBox);
}
}
<foo:mycheckbox ................/>
Define your own class and use the foo:mycheckbox in style file.
I am applying the MVVM pattern to a project. I have a UserControl that has a button which is bound to a command exposed by the ViewModel.
Since the button is visible, it's calling continuously the CanExecute method of the button. Something tells me that this carries a performance penalty, but I'm not sure. Is this the expected behavior? or is there a better way of having a button bound to a command?
Thank you.
Sorry, I found out what was happening.
This is the implementation of 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
}
I had incorrectly assumed the system was requerying ALL commands automatically. What it actually does is hook to each Command's CanExecuteChanged event, and RelayCommand basically links its CanExecuteChanged event to the CommandManager's RequerySuggested event, so each time the system "suggests" a requery, it was in fact requerying all my RelayCommands.
Thank you.