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.
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()));
}
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.
Related
I'll give some details below, but briefly I have a problem wherein a button in my WPF application will disable itself if I click somewhere else in the application. This button is linked to a Command but there is absolutely NOTHING bound to the IsEnabled property of the button and the Command CanExecute callback just sets e.CanExecute to true.
I saw this similar SO question (Weird problem where Button does not get re-enabled unless the mouse is clicked) but it was not helpful.
The application is simple and consists of a DockPanel divided into 4 parts. The left section contains a DataGrid and the right section contains a UserControl that also contains a couple DataGrids as well as the offending Button. It's so weird, but if I click on any row in the left DataGrid, the Button in the right section becomes disabled. The only way I can then re-enable it is to click on any row in either of the DataGrids in the right section!
Again, there IS absolutely nothing bound to the IsEnabled property of the button or any other code/markup implicitly in place that would allow this to happen.
Some relevant code snippets:
UserControl Command bindings:
<UserControl.CommandBindings>
<CommandBinding Command="cmd:DBScriptCommands.LoadScripts" CanExecute="cmdLoadScripts_CanExecute" Executed="cmdLoadScripts_Executed" />
<CommandBinding Command="cmd:DBScriptCommands.RunScripts" CanExecute="cmdRunScripts_CanExecute" Executed="cmdRunScripts_Executed" />
</UserControl.CommandBindings>
Button xaml:
<Button IsEnabled="True" x:Name="btnLoadScripts" Command="cmd:DBScriptCommands.LoadScripts">
<StackPanel HorizontalAlignment="Stretch">
<Image Source="/Images/folder-open.png" />
<TextBlock>Load Scripts</TextBlock>
</StackPanel>
</Button>
CanExecute for Command:
private void cmdLoadScripts_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
This has me baffled and any ideas are appreciated. If more information is needed, please let me know.
Edit 1:
Seems like it is something to do with the Command (still not sure what) - if I remove the Command parameter from the Button, the problem goes away - not useful because I want the button to trigger the Command, but interesting. In the CanExecute(), if I set e.CanExecute to false, the button is always disabled which makes sense. When it is set to true (like it is now) then I have the problem I've describe where it seems like something is setting it to false by magic sometimes.
Thanks
I am new to WPF and I see the best pattern call MVVM. I have try to deep in it and I see that the command can only execute on a button or menuitem, etc. But I have a doubt how to execute the ViewModel command when I'm focusing on a textbox and hit the enter key when I finish my editing.
I have google this but I got nothing from all that answer. So hope all of you help me. How to execute command when hit the enter key in textbox?
In my opinion the easiest way is to use a KeyBinding, which allows you to bind a KeyGesture to an ICommand implementation.
In your case, you can write in your XAML something like this:
<TextBox AcceptsReturn="False">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding YourCommand}" />
</TextBox.InputBindings>
</TextBox>
So when your TextBox is focused and you press Enter, YourCommand will be executed.
I hope it can help you.
You can achieve your requirement using behaviors in WPF.
In XAML,
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<TextBox Text="MyText">
<i:Interaction.Behaviors>
<i:BehaviorCollection>
<EventToCommand EventName="TextChanged" Command="{Binding ViewModelCommand}">
**// You can provide other events to be triggered in the EventName property based on your requirement like "Focused" or "UnFocused".Focused event will be fired if you enter into edit mode and UnFocused event will be triggered if you press enter key.**
<i:BehaviorCollection>
</i:Interaction.Behaviors>
</TextBox>
In ViewModel.cs,
Public class ViewModel
{
private Command viewCommand;
public ViewModel()
{
viewCommand = new Command(CommandMethod);
}
public Command ViewModelCommand
{
get { return viewCommand }
set { viewCommand = value}
}
private void CommandMethod()
{
//This method will hit if you modify enter/delete text in the TextBox
}
}
I am using C# and XAML and Template10. I have an AutoSuggestBox in a command bar. It is all working fine but the dropdown list does not close when I make my selection. The selection activates new content that is covered up by the stuck dropdown. It only closes if I click on the icon on the textbox, not the listed item that was selected. How is this dropdown closed programmatically in C# or XAML?
<AutoSuggestBox x:Name="asb2"
RelativePanel.AlignRightWithPanel="True"
PlaceholderText="Search for..."
TextChanged="asb_TextChanged"
QueryIcon="Find"
QuerySubmitted="asb_QuerySubmitted"
SuggestionChosen="asb_SuggestionChosen"
Margin="10,0"
Height="40"
MinWidth="250"
BorderThickness="1" />
Code behind:
private void asb_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
asb2.IsSuggestionListOpen = false;
var contact = args.SelectedItem as AutoContact;
sender.Text = string.Format("{0} *** ({1})", contact.Word, contact.Nick);
AddressBox.Text = contact.Url;
GoButton_Click();
}
Solved! I was clearing the last AutoSuggestBox text before reading the text. This kept the drop down box open because no suggestion was there to make it disappear. Moved clearing the AutoSuggestBox to OnFocus. This allowed the text to end the dropdown. When I click the AutoSuggestBox again starts empty.
On keyboard button name as BackSpace do not work as backspace for multiple textBoxes.
for single textbox i write this code and successfully .
textbox.text = textbox.Text.Remove(textbox.Textlength-1,1);
but not work for multiple textboxes.
Edit Note that this is an WPF answer but the question is about winforms. I'll leave the answer for now in case someone looks for the same thing with WPF.
You can use the FocusManager.IsFocusScope property:
<StackPanel>
<StackPanel x:Name="tbElements" FocusManager.IsFocusScope="True">
<TextBox x:Name="tb1" Margin="3" VerticalAlignment="Top"/>
<TextBox x:Name="tb2" Margin="3" VerticalAlignment="Top"/>
</StackPanel>
<Button Content="Test" Margin="3" Height="26" Click="Button_Click"/>
</StackPanel>
Then the textboxes are managed in a separate logical focus scope
private void Button_Click(object sender, RoutedEventArgs e)
{
var test1 = FocusManager.GetFocusedElement(this);
var test2 = FocusManager.GetFocusedElement(tbElements);
}
The result will be, that test1 references the clicked button, because it has the current focus, but test2 references the last focused textbox, because it has the local focus within its separate logical focus scope.
An alternative would be to set the Button property Focusable to False, so if a textbox has the focus when the button is clicked, the focus stays within the textbox. This prevents keyboard navigation to the button but since the button is part of the screen keyboard, this may be acceptable or even desired behavior.
I am pretty sure that OP does not want to perform backspaces on multiple textboxes, rather wants Backspace button to affect textbox currently focused, so:
To emulate a keyboard stroke use SendKeys.Send(string keys) instead of current implementation. This will perform BACKSPACE on control which has focus:
private void backspace_Click(object sender, EventArgs e)
{
//{BACKSPACE}, {BS}, or {BKSP}
SendKeys.Send("{BACKSPACE}");
}
What I want is when for the currently focused textbox to lose focus when the user hits the enter key. The only way I can think to achieve this is by using input bindings in XAML to bind to a command in code that passes down the entire textbox control to the viewmodel. I don't like this approach and was hoping someone had a 'clean' way of approaching this problem.
You could create a custom textbox and put this in the controls code:
public partial class CustomTextBox : TextBox
{
public CustomTextBox()
{
InitializeComponent();
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if(e.Key == Key.Return)
Keyboard.ClearFocus();
}
}
Then just use your custom textbox wherever you want that particular behaviour.
Quite often you get a password box on login whereby you need to allow the enter key.
<PasswordBox VerticalAlignment="Center" x:Name="txtPassword" Template="{StaticResource PassBoxBaseControlTemplate}" Height="25" BorderBrush="Black" Width="165.031">
<PasswordBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding ComLoginClickOK}" CommandParameter="{Binding ElementName=txtPassword}"/>
</PasswordBox.InputBindings>
</PasswordBox>