Wpf – How to lose focus on button press

lost-focusmvvmwpf

Simplified:
In my view I've got a xaml page containing a button and some kind of TextBox. The button is bound to a DelegateCommand in the ViewModel, the editbox is bound to some property in the ViewModel.

View:
<Button Command="{Binding MyCommand}"/>
<TextBox Text="{Binding MyString}"/>

ViewModel:
public DelegateCommand MyCommand { get; set; }
public String MyString { get; set; }

Now when the user enters something into the box and clicks on the button, the button does not receive a focus change event. So it will not update it's content to the property. So the property MyString does not reflect the content of the TextBox on clicking the button. So whatever processing MyCommand is doing, it is working with old data and not the current input.

Now if this really was just a TextBox I'd add UpdateSourceTrigger=PropertyChanged to the binding and I'd be good.
But in this case the edit control is a bit more complex and needs to do some validation to the content.
So I need some kind of "lost focus" signal when pressing the button by mouse.

My problem is: in MVVM the code behind for the button does not have any access to the view, so it can't make it lose the focus.

Is there any way in xaml (e.g. in the view) to make the button get the keyboard focus when it is clicked by mouse? That would be the easiest way for my custom control to get a "lost focus" message.

Best Answer

Re: Is there any way in xaml (e.g. in the view) to make the button get the keyboard focus when it is clicked by mouse? > A button does receive keyboard focus when it is clicked – provided the IsEnabled, Focusable, and IsHitTestVisible properties are all set to true as they are by default. To set keyboard focus programmatically call Keybaord.Focus as shown in the example below.

Contrary to a popular meme, Commands do not HAVE to be processed in the VM. If, on command execution, the view needs to be changed independently of the VM, the command can be handled in the view. In fact this is the native pattern for WPF.

The following example shows using the Command property on a button to process a command in the view. For simplicity the example does not have a VM. Even though the command is processed in the view, if there were a VM, the code behind in the view could make calls into it.

public partial class MainWindow : Window
{
    public static readonly RoutedUICommand MyCommand = new RoutedUICommand("My Command", "MyCommand", typeof(MainWindow));
    public String MyString { get; set; }

    public MainWindow()
    {
        MyString = "some text";
        DataContext = this; // this simple example has no VM 
        InitializeComponent();
    }
    private void MyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        Button1.Content = MyString;
        Keyboard.Focus(Button1);   
    }
}
<Window x:Class="fwLoseFocus.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:me="clr-namespace:fwLoseFocus">
    <Window.CommandBindings>
        <CommandBinding Command="me:MainWindow.MyCommand" Executed="MyCommand_Executed"/>
    </Window.CommandBindings>
    <StackPanel>
        <TextBox Text="{Binding MyString}"/>
        <Button x:Name="Button1" Command="me:MainWindow.MyCommand"/>
    </StackPanel>
</Window>
Related Topic