I have a user control which is part of an app that is composed using Prism. It has this 'Back' Button:
<Button Content="Back"
Command="{Binding BackCommand}"
Padding="5 12 5 2" />
Sometimes this button doesn't execute the command. The view model provides this command:
public class BackCommand : ICommand
{
private readonly IInterviewController _controller;
public BackCommand(IInterviewController controller)
{
_controller = controller;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_controller.MovePreviousTopic();
}
public event EventHandler CanExecuteChanged;
}
In addition the user control has a 'Next' button that moves the user though the a series of branching questions based on what the user selects in a second control. The back button is supposed to take the user to the previous question. The back button usually executes the bound command so I know the binding works. Sometimes the user has to click the back button twice before the command will fire. I replaced the CanExecute body to always return true (as shown above) still the button stops working.
I put temporary event handlers on the button and discovered that when the command fails to execute:
- the button is enabled
- the binding is still set
- the PreviewMouseDown event on the button fires
- the Click event does not fire (even if I remove the command)
- the command's Execute method is not called.
Every question on SO I'm finding about commands not firing, the OP was having one issue or another binding the command. Since my command is bound, I'm not finding much useful.
Edit #2: I have discovered the cause of the issue. One of the components composed into the application is trying to control focus. To reproduce the issue, paste this into a window:
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Current count:"/>
<TextBlock Text="{Binding Counter}"/>
</StackPanel>
<CheckBox x:Name="MyCheckbox" IsChecked="{Binding MaintainFocus}" LostFocus="MaintainFocus" >Maintain Focus</CheckBox>
<Button Command="{Binding MyCommand}" Content="Test" Width="100" />
</StackPanel>
Paste this into the window's code behind: public partial class MainWindow : Window { private readonly ViewModel _vm;
public MainWindow()
{
DataContext = _vm = new ViewModel();
InitializeComponent();
}
private void MaintainFocus(object sender, RoutedEventArgs e)
{
if (_vm.MaintainFocus)
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(() => MyCheckbox.Focus()));
}
}
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
MyCommand = new TestCommand(this);
}
public ICommand MyCommand { get; set; }
private int _counter;
public int Counter
{
get { return _counter; }
set
{
_counter = value;
OnPropertyChanged();
}
}
public bool MaintainFocus { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class TestCommand : ICommand
{
private readonly ViewModel _viewModel;
public TestCommand(ViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_viewModel.Counter++;
}
public event EventHandler CanExecuteChanged;
}
Now, if you check the Maintain Focus checkbox, the Test button will not fire.
Background="#00000000"
on the border inside button's ControlTemplate. I'm sure it will solve the problem. – Maxim