1

I have the following textbox in a user control.

<!-- This is the user input TextBox, users type commands here and hit enter or press the send command button -->
<TextBox Text="{Binding CommandText}" Background="Transparent" BorderBrush="{StaticResource brushWatermarkBorder}" Name="txtUserEntry">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding BindKeyCommand}"
                CommandParameter="{Binding ElementName=txtUserEntry, Path=Text}"
                Key="Return"
                Modifiers=""/>
    </TextBox.InputBindings>
</TextBox>

and button.

<!-- This button serves as an alternative to hitting the enter key with text box focus. -->
<Button Command="{Binding BindKeyCommand}"  CommandParameter="{Binding ElementName=txtUserEntry, Path=Text}" Grid.Column="2">
    <TextBlock>
                Send Command
    </TextBlock>
</Button>

When a user types into the box and uses the return key too send the command, the command is sent through the BindKeyCommand successfully (a messagebox pops up to confirm this) and focus is maintained on the text box.

However, when a command is sent using the Button, the command is, once again, successful, but the focus on the text box is lost.

I have attempted to implement the answers here but all to no avail. Could someone please explain to me, either, how to correctly implement the answers here, including what to put in the view model, or, an alternative method such that, on button press, the keyboard focus is assigned back to the textbox. It might be important to note, just as in the linked question, I am using MVVM.

UPDATE: Trying to carry out steps by DT Sawant

Step 1:

ApplicationName.Tools.FocusExtension contains all of the text within second highest rated answer. Extension is in namespace ApplicationName.Tools

Step 2:

Added new property;

private bool isTxtUserEntryFocused = false;
public bool IsTxtUserEntryFocused
{
    get
    {
       return isTxtUserEntryFocused;
    }
        set
        {
            isTxtUserEntryFocused = value;
            OnPropertyChanged("IsTxtUserEntryFocused");
        }
    }

Step 3:

Added namespace reference; xmlns:Tools ="clr-namespace:WPFLocalDataConnect.Tools"

Step 4:

Bound IsFocused property; Tools:FocusExtension.IsFocused="{Binding IsTxtUserEntryFocused}"

Step 5:

Initializing in viewmodel thusly;

        public void ExecuteBindKeyCommand(string param)
    {
        if (String.IsNullOrWhiteSpace(param))
        {
            MessageBox.Show("No command given.");
            this.CommandText = string.Format("");
            IsTxtUserEntryFocused = true;
        }
        else
        {
            MessageBox.Show(string.Format("CommandInvoked: {0}", param));
            History = string.Format("{0} {2} {1}", History, param, Environment.NewLine);
            this.CommandText = string.Format("");
            IsTxtUserEntryFocused = true;
        }
    }

Now all steps are completed I tested the project. It did not work but some interesting things to note;

Pressing the button WITHOUT first focusing the textbox results in "no command" message followed by focus move to textbox. Pressing the button after clicking in the textbox, either entering or not entering text results in "no command" or "command invoked" messages respectively followed by no focus move to the textbox. THIS IS SO CONFUSING.

Community
  • 1
  • 1
Lewis Heslop
  • 574
  • 2
  • 8
  • 25
  • 1
    You can do this in code behind. You SHOULD NOT do such things in ViewModel since it's only a UI task and ViewModel should not know about the view. It's not breaking MVVM it's acutally a correct way to MVVM – MajkeloDev Aug 21 '15 at 08:43

2 Answers2

0

You can do something like this in code behind to set the focus

 <Button Click="MyButton_Click" Name="MyButton" Command="{Binding BindKeyCommand}"  CommandParameter="{Binding ElementName=txtUserEntry, Path=Text}" Grid.Column="2" >
<TextBlock>
            Send Command
</TextBlock>

 private void MyButton_Click(object sender, RoutedEventArgs e)
    {
         Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() => txtUserEntry.Focus()));
    }
adminSoftDK
  • 2,012
  • 1
  • 21
  • 41
  • I am new to this. Can you please explain what you mean by "do something like this"? Do I just plop it in any old where? – Lewis Heslop Aug 21 '15 at 08:47
  • You could do a click event on your button, and use that code in it. That will set the focus back to your textbox. (please see the edit) – adminSoftDK Aug 21 '15 at 08:57
  • I have done as you have described, but still no avail. The button press does indeed carry out the action you described. This happens before the confirmation message box appears. Once OK is pressed on the messagebox, the focus drops to the button again. – Lewis Heslop Aug 21 '15 at 09:45
  • I see, may I ask why do you actually popup the messagebox from the viewmodel? and not the code behind? – adminSoftDK Aug 21 '15 at 10:06
  • I take the user input from the text box, and run it into a command checking function. This determines whether the 'command' is correct or is false and if the 'command' is false a message box displays saying "Please try again", if the 'command' is true it is actioned by an interpreting function and added to a log of commands. I don't think that, using mvvm, I can do any of this in the code behind. This is why i pop the messagebox in the view model – Lewis Heslop Aug 21 '15 at 10:16
  • I didnt try this, but you could setup one way binding on your button command, and get rid of the command parameter in xaml, then do click event, then from your code behind, you can go ButtonName.Command.Execute(txt.Text - this is your command parameter), then everything will work as it was, but now the next line can be that line which sets the focus back to your textbox, after your command run and the messagebox displayed. – adminSoftDK Aug 21 '15 at 11:29
0

As you have attempted to solve your issue with the help of this link. I will explain the steps to implement the same solution:

step 1: Add new class FocusExtension as given in above link.

step 2: Add new property IsTxtUserEntryFocused(you can give any name) in your viewmodel

step 3: Add namespace reference of FocusExtension Class in your XAML

step 4: Bind IsFocused property of FocusExtension class to your viewmodel property. As shown in below:

<TextBox local:FocusExtension.IsFocused="{Binding IsTxtUserEntryFocused}" /> 

step 5: Now in your button command which you might have implemented in your view model. Initialize

IsTxtUserEntryFocused=true.

The focus is not retaining on Textbox because your displaying message box. So focus goes to message box and it does not come back to your window.

You should add this line after your displaying messagebox

 Application.Current.MainWindow.Focus();//Bring focus to your window where text box is present

That's it.

Community
  • 1
  • 1
DT sawant
  • 1,201
  • 2
  • 10
  • 21