I have a button in a Windows 8.1 'universal' app bound to a RelayCommand
that is not updating to disabled as expected, based on the return value of CanExecute()
. Implementation details are below, but basically, the RelayCommand
is initialised to return false, changes to enabled as expected, but doesn't return to disabled as expected.
UI flow is once the user selects an item from a combobox (bound to a property), the .RaiseCanExecuteChanged()
is called and returns true, and the button updates to enabled as expected. A second combobox (now visible) is bound to another property, which when changed runs a method to set a validation property, which when changed calls .RaiseCanExecuteChanged()
. This time, when I expect to see the button disabled, it isn't, despite CanExecute()
returning false. Funnily enough, the delegate method that is the action doesn't run if the button is then clicked, but I need the button disabled, since the click
method of the button is Frame.GoBack()
RelayCommand class:
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
CanExecute method:
private bool CanAcceptTransportProfile()
{
if (IsTPInEditMode == false) return false;
if (SelectedTransport == null) return false;
if (IsSubPropertiesValid == false) return false;
return true;
}
Initial property and change:
public Unit SelectedTransport
{
get { return _selectedTransport; }
set
{
if (_selectedTransport != value)
{
_selectedTransport = value;
RaisePropertyChanged("SelectedTransport");
OnSelectedTransportChange();
}
}
}
private void OnSelectedTransportChange()
{
switch (SelectedTransport == null)
{
case true:
IsTransportSelected = false;
IsUnitsPerTransportValid = true;
IsSharingWithValid = true;
IsNestingValid = true;
break;
case false:
IsTransportSelected = true;
ShowUnitsPerTransportSelector = IsAllowedToShareTransport ? false : true;
break;
}
CommandAcceptTransportProfile.RaiseCanExecuteChanged();
}
Second property change:
public int UnitsPerTransport
{
get { return _unitsPerTransport; }
set
{
if (_unitsPerTransport != value)
{
_unitsPerTransport = value;
RaisePropertyChanged("UnitsPerTransport");
OnUnitsPerTransportChange();
}
}
}
private void OnUnitsPerTransportChange()
{
List<int> unitoptions = UnitHelper.UnitRangeFromSquadSize(this.SquadSize);
if (!unitoptions.Contains(_unitsPerTransport))
{
foreach (int num in unitoptions)
{
if (_unitsPerTransport < num)
{
if (num % _unitsPerTransport != 0)
{ goto Invalid; }
}
else
{
if (_unitsPerTransport % num != 0)
{ goto Invalid; }
}
}
goto Valid;
}
else
{ goto Valid; }
Valid:
IsUnitsPerTransportValid = true;
IsSubPropertiesValid = (IsUnitsPerTransportValid && IsNestingValid && IsSharingWithValid && IsTotalUnitsRequiredValid) ? true : false;
Invalid:
IsUnitsPerTransportValid = false;
IsSubPropertiesValid = false;
}
IsSubPropertiesValid
raises CommandAcceptTransportProfile.RaiseCanExecuteChanged()
when it changes. The UnitHelper
is a static class and just returns a list of ints
. the method then checks the selected int from the combobox and goes to valid/invalid accordingly. it is when this sets IsSubPropertiesValid
to false I expect to see the button become disabled, and it isn't.
I have been using the RelayCommand
in this fashion throughout my project and it has worked in every instance as expected, except this one, which has more complex validation/Onproperty change calls surrounding it, so I suspect it has something to do with that, but it is beyond my self taught knowledge to resolve.
Try to implement INotifyPropertyChanged , a sample can look like this:
public class RelayCommand : ICommand, INotifyPropertyChanged
{
#region INotify
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseCanExecuteChanged()
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, "CanExecute");
}
}
#endregion
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.