I have some custom editable listbox on my wpf window. I also have a viewmodel class with Property Changed which looks like that:
public bool HasChanges
{
get
{
return customers.Any(customer => customer.Changed);
}
}
So, I would like to bind my Save button to this property:
<Button IsEnabled="{Binding HasChanges, Mode=OneWay}"...
My question is how to update Save button if one of the listbox rows is changed?
The proper way to deal with buttons is to implement ICommand interface. Here is an example from my solution:
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("execute");
_execute = execute;
_canExecute = canExecute;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
#endregion
}
You can then databind to button like this:
<Button Command="{Binding MyCommand}" .../>
Whats left is to declare an ICommand
property on your viewmodel:
public ICommand MyCommand { get; private set; }
//in constructor:
MyCommand = new RelayCommand(_ => SomeActionOnButtonClick(), _ => HasChanges);
The state of the button will then automatically update on most changes. If it doesnt for some reason - you can force the update by calling CommandManager.InvalidateRequerySuggested
In order for WPF to react to changes in properties, the class must implement INotifyPropertyChanged
interface. You need to send notifications every time a customer is changed, like this:
class CustomerList : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private List<Customer> customers = ...
public bool HasChanges {
get {
return customers.Any(customer => customer.Changed);
}
}
// Callers who change customers inside your list must call this method
public void ChangeCustomer(Customer c) {
// Do whatever you need to do, ...
...
// then send out the notification to WPF
OnPropertyChanged("HasChanges");
}
protected void OnPropertyChanged(string name) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(name));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With