4

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.

Sam
  • 28,421
  • 49
  • 167
  • 247
  • Shouldn't you be using Command={Binding MyCommand} ? also...if you intention is to have the Button show the Text that is type in..then you need to bind to it's Text similar to this.... http://leecampbell.blogspot.co.uk/2008/12/wpf-commandtext.html ... unless your DelegateCommand somehow gets a dependency to your MyString. – Colin Smith Aug 21 '12 at 13:05
  • Oh yes, sorry about that typo!! And I don't want the button to show the text, it calls some routine which is processing the input. – Sam Aug 21 '12 at 13:15
  • Woudl it be possible to use the validation system already built into WPF ? Take a look at ValidationRules, and IDataErrorInfo, and ValidatesOnDataErrors. http://www.codeproject.com/Articles/15239/Validation-in-Windows-Presentation-Foundation ... http://www.hardcodet.net/2009/01/combinding-wpf-validation-rules-and-idataerrorinfo-to-validate-conversion-errors – Colin Smith Aug 21 '12 at 13:46
  • @colinsmith, interesting idea. Validation in this case is a query to a database, depending on field content, which is behind some WCF service. I don't really know how I'd use the WPF validation for this. Additionally it might change the field content, which usually is not something IDataErrorInfo is build for, isn't it? – Sam Aug 21 '12 at 13:54
  • Have a look here: http://stackoverflow.com/questions/10401414/delayed-input-validation-with-wpf – Colin Smith Aug 21 '12 at 13:58

2 Answers2

3

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>
SpeedCoder5
  • 8,188
  • 6
  • 33
  • 34
  • Aah, damn, sorry, my mistake: it is not a button, it is a menu item. No wonder it didn't work. – Sam Aug 22 '12 at 09:50
  • 1
    No problem. With a menu item it becomes important to understand WPF focus scopes and the difference between logical focus and keyboard focus. Check out Mark Smith's article "It's Bascially Focus": [link](http://julmar.com/blog/mark/?p=52). – SpeedCoder5 Aug 22 '12 at 14:16
1

Is it not possible to still have the click event for the Button and have the code behind make the textbox lose focus?

private void Button_Click(object sender, RoutedEventArgs e) { 
    FocusManager.SetFocusedElement(this, null); 
} 

Is the following answer relavant to you?

WPF Reset Focus on Button Click

Community
  • 1
  • 1
Manoj
  • 5,011
  • 12
  • 52
  • 76
  • Since the app is MVVM, the button has no click event but is instead bound to a Command in the ViewModel, and the ViewModel has no access to the Button, since the Button is contained in the View. – Sam Aug 21 '12 at 13:26
  • So in short: I can't access the button (or any other part of xaml) from the ViewModel. – Sam Aug 21 '12 at 13:35
  • I assumed the click event was still available even if you bound the button to a command Or you might be trying to maintain the purity of MVVM by having an empty code behind. In the second case I assume having code behind to manipulate the UI is acccepted to certain extend. http://stackoverflow.com/questions/6421372/why-to-avoid-the-codebehind-in-wpf-mvvm-pattern – Manoj Aug 21 '12 at 13:55
  • Interesting. So if an button/menuitem has both Command and Click, both will be called? – Sam Aug 22 '12 at 09:52
  • 1
    @Sam I tried this with a Button and both of them were called. – Manoj Aug 27 '12 at 11:02