1
votes

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.

2
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

2 Answers

0
votes

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()));
    }
0
votes

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.