WPF- Selection Brush is not working, I am selecting 'H' in my case but it is not working.
Here is my code :
XAML :
<TextBox Text="Hello" Height="49" Name="textBox2" Width="547" />
C#
textBox2.SelectionStart = 0;
textBox2.SelectionLength = 1;
textBox2.SelectionBrush = Brushes.Red;
Try this
textBox2.Focus();
textBox2.SelectionStart = 0;
textBox2.SelectionLength = 1;
textBox2.SelectionBrush = Brushes.Red;
An alternative solution is to trick the TextBox into thinking it has not lost focus. This way, you're not actually moving focus back to the TextBox.
For this to work, you'd have to set focus on the TextBox at least once, like when the user enters the initial text, or by calling textBox2.Focus() from the constructor.
Markup:
<TextBox Height="49" x:Name="textBox2" LostFocus="TextBox2_OnLostFocus" />
Code-behind:
private void TextBox2_OnLostFocus(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
Related
I'm using WPF
I want to auto-tab to the next texbox when 'MaxLength' is reached.
I found this code : XAML Trigger Auto-tab when MaxLength is Reached
And it's working. But the problem is, I can't delete text when the MaxLength is reached !
I can't change the actual text too.
Do you have an idea to allow me to modify, or delete text from a MaxLength reached textbox ?
My XAML :
<TextBox Grid.Column="0" Name="txtC1" Margin="5" MaxLength="7" PreviewKeyDown="txt1_PreviewKeyDown"></TextBox>
<TextBox Grid.Column="1" Name="txt2" Margin="5" MaxLength="12" PreviewKeyDown="txt2_PreviewKeyDown"></TextBox>
<TextBox Grid.Column="2" Name="txt3" Margin="5" MaxLength="12" PreviewKeyDown="txt3_PreviewKeyDown"></TextBox>
Code Behind
private void txt1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
// Auto-tab when maxlength is reached
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
The problem is that you are using the event on a keyDown and that means that when backspace or delete is pressed, the event is triggered but the text hasn't changed until the keyDown event is done, so the code will always validate with the same number of characters in the textBox and it will take one more character to type in the box to trigger the change of focus in your case.
You can do something like this instead
XAML
<TextBox Grid.Column="0" Name="txtC1" Margin="5" MaxLength="7" TextChanged="txt1_TextChanged"></TextBox>
<TextBox Grid.Column="1" Name="txt2" Margin="5" MaxLength="12" TextChanged="txt2_TextChanged"></TextBox>
<TextBox Grid.Column="2" Name="txt3" Margin="5" MaxLength="12" TextChanged="txt3_TextChanged"></TextBox>
Code
private void txt1_TextChanged(object sender, TextChangedEventArgs e)
{
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
You can still do some keyDown event for something else e.g.: Allowing some key only like numbers or special numbers, but it is better to validate the text lenght with a textChanged event.
I resolved my own problem. Thanks to differents answers I got, I used them a little.
This is my new code behind :
private void txt1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
// Auto-tab when maxlength is reached
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
if(e.Key != Key.Delete && e.Key != Key.Clear && e.Key != Key.Back && ((TextBox)sender).SelectionLength == 0)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
}
And it's working.
I need to edit some hierarchical structure and I use TreeView with TextBoxes
Short example
<TreeView>
<TreeView.Items>
<TreeViewItem Header="Level 0">
<!-- Level 1-->
<TextBox Margin="5"
BorderThickness="1" BorderBrush="Black" />
</TreeViewItem>
</TreeView.Items>
</TreeView>
When I type in TextBox, +, -, letters and digits work fine, arrows work but when I press -, Level 0 item collapses and when I type *, nothing happens
How should I handle - and * to see them in TextBox as expected?
Edit:
- works if typed as Key.OemMinus but not from numeric keyboard as Key.Subtract
* works if typed as Shift+Key.D8 but not from numeric keyboard as Key.Multiply
finally solved the problem with Key.Subtract
I added handler to PreviewKeyDown on TextBox
<TextBox Margin="5" BorderThickness="1" BorderBrush="Black"
PreviewKeyDown="TextBoxPreviewKeyDown"
/>
on receiving Key.Subtract, KeyDown is marked as handled and then i manually raise TextInput event as explained in this answer (How can I programmatically generate keypress events in C#? )
private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Subtract)
{
e.Handled = true;
var text = "-";
var target = Keyboard.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;
target.RaiseEvent(
new TextCompositionEventArgs
(
InputManager.Current.PrimaryKeyboardDevice,
new TextComposition(InputManager.Current, target, text)
)
{
RoutedEvent = routedEvent
});
}
}
I can suggest a keydown event for the textboxes that you have.
<TextBox Margin="5" KeyDown="TextBox_KeyDown"
BorderThickness="1" BorderBrush="Black" />
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
TextBox txt = sender as TextBox;
if(e.Key == Key.Subtract)
{
txt.Text += "-";
txt.SelectionStart = txt.Text.Length;
txt.SelectionLength = 0;
e.Handled = true;
}
else if (e.Key == Key.Multiply)
{
txt.Text += "*";
txt.SelectionStart = txt.Text.Length;
txt.SelectionLength = 0;
e.Handled = true;
}
}
It's not a good solution but it works. If you have any other "problem" keys, you can add an if to the event.
SelectionStart and SelectionLength are for positioning cursor at the end of textbox. And e.Handled = true; does prevent the default behaviour.
Evening all, I've run into an issue with the SelectionChanged (TabControl) event being call before the LostFocus (TextBox) event.
This is a problem since the SelectionChanged is triggered during a tab change, that intern resets the ListView.SelectedIndex (TabControl>TabItem>ListView) to -1.
The textbox uses LostFocus to update/validate it's textbox.text which depend upon the SelectedIndex. The text in the textbox is stored/retrieved from a List<string> and because the index changed, the List happens to go out of bounds.
I've looked around, tired a few things also a "hack-y" approach which didn't really help.
<TabControl SelectionChanged="SelectionChanged_Tab"
<TabItem .../>
<TabItem .../>
</TabControl>
<Grid>
<Label .../>
<TextBox Name="Name" LostFocus="Lost_Focus" .../>
</Grid>
Code:
private void SelectionChanged_Tab(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
ListView1.SelectedIndex = -1;
ListView2.SelectedIndex = -1;
}
}
private void Lost_Focus(object sender, RoutedEventArgs e)
{
TextBox textbox = sender as TextBox;
int Index = ListView.SelectedIndex;
if (string.IsNullOrEmpty(textbox.Text) || textbox.Text == "0")
{
textbox.Text = "0";
}
switch (textbox.Name)
{
case "Name":
SomeList[Index].AProperty = textbox.Text;
break;
}
}
OK, so after think about the problem from a different perspective, I decided to simple make the TabControl, an Focus-able event and simple make it focus when selection changes:
<TabControl SelectionChanged="SelectionChanged_Tab" Focusable="True"
<TabItem .../>
<TabItem .../>
</TabControl>
Code:
private void SelectionChanged_Tab(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
ListView2.Focus();
ListView1.SelectedIndex = -1;
ListView2.SelectedIndex = -1;
}
if (ListView2.SelectedIndex == -1)
{
ListView1.Focus();
}
}
I know it's not the most elegant solution (In the process or re-factoring) but this seems to get the job done.
Trying to have a default value for my radio buttons, but get flagged an NullReferenceException error.
private void rbImperial_Checked(object sender, RoutedEventArgs e)
{
txtInches.Visibility = Visibility.Visible;
lblInches.Visibility = Visibility.Visible;
lblWeight.Text = "lbs";
lblHeight.Text = "Feet";
}
private void rbMetric_Checked(object sender, RoutedEventArgs e)
{
lblHeight.Text = "cm";
txtInches.Visibility = Visibility.Collapsed;
lblInches.Visibility = Visibility.Collapsed;
lblWeight.Text = "kg";
}
rbImperial is the defaulted radio button that should be checked.
XAML:
<RadioButton x:Name="rbMetric" Content="Metric" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="132,244,0,0" Checked="rbMetric_Checked" ClickMode="Press"/>
<RadioButton x:Name="rbImperial" Content="Imperial" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="132,199,0,0" Checked="rbImperial_Checked" IsChecked="True" ClickMode="Press" />
If I don't have the rbImperial Checked property to be True to make it defaulted to be selected it runs perfectly fine.
What am I missing?
My issue when I try to run it.
Try setting the default value in the constructor. Not the prettiest method, but it should work. Alternatively, you can bind it to the ViewModel; that should work as well.
When you activate an application, a textbox with text "hello" will appear.
My question is:
When you click on the textbox in order to make input data, I want to remove the text automatically in XAML code, how do I do it?
Handle the UIElement.GotFocus event, and in the handler, clear the text. You'll also want to remove the handler, so that if you click on the TextBox a second time you don't lose what you've already entered.
Something like this:
XAML:
<TextBox Text="Hello" GotFocus="TextBox_GotFocus" />
Code-behind:
public void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.Text = string.Empty;
tb.GotFocus -= TextBox_GotFocus;
}
A XAML implementation that requires no code-behind. This is copied from the template of a custom control I built, and you'd probably want to make this a custom control yourself.
The basic idea is that there are two TextBoxes in a Grid. The top one is the actual control that the user interacts with, but it's invisible (its 'Opacity' is zero) unless it contains text or has the focus. The bottom one contains the prompt text. It will only be visible when the TextBox on top of it is not, and it will never get the focus.
You'll probably have to mess around with the binding on the editable TextBox, but this should get you started.
<Grid>
<TextBox Text="This is the prompt text"
FontStyle="Italic"
Foreground="LightGray"
Focusable="False">
</TextBox>
<TextBox Text="{Binding TextProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Focusable="True">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Opacity"
Value="1" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Opacity"
Value="0" />
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
You have to implement both GetFocus and LostFocus events. In this way you can set the default text back in lost focus event if no text is entered.
private const string defaultText = "Hello";
private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
myTextBox.Text = myTextBox.Text == defaultText ? string.Empty : myTextBox.Text;
}
private void myTextBox_LostFocus(object sender, RoutedEventArgs e)
{
myTextBox.Text = myTextBox.Text == string.Empty ? defaultText : myTextBox.Text;
}
To expound upon Donut's answer so that your textbox will keep the text a user inputs unless it's purely whitespace, here's a solution that I use:
XAML
<TextBox Text="Search..."
Width="250"
Foreground="LightGray"
GotFocus="TextBox_GotFocus"
LostFocus="TextBox_LostFocus" />
C#
void TextBox_GotFocus( object sender, RoutedEventArgs e )
{
TextBox box = sender as TextBox;
box.Text = string.Empty;
box.Foreground = Brushes.Black;
box.GotFocus -= TextBox_GotFocus;
}
void TextBox.LostFocus( object sender, RoutedEventArgs e )
{
TextBox box = sender as TextBox;
if( box.Text.Trim().Equals( string.Empty ) )
{
box.Text = "Search...";
box.Foreground = Brushes.LightGray;
box.GotFocus += TextBox_GotFocus;
}
}
I just did this:
XAML:
<TextBox Name="Filename"
Grid.Column="0"
Height="23"
Margin="10,9,0,0"
Text="Enter Export Filename here"
Width="193"
GotFocus="Filename_GotFocus"
/>
Code behind:
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.Text = "";
}
you can use Tap method also , it is also working
private void tb1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
tb1.Text = "";
}
Please don't over complicate the answer several ways to skin a cat but,
less code the better I would presume.
Petermac's option is the way to go for me.
Add "GotFocus" in the main Xaml window to the control eg."textbox"
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.Text = "";
}
or I like this option
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.clear();
}
the question asked was just to empty the textbox.
I want to update Donut's answer.(applicable for windows 8)
Code behind code be
public void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
if(tb.Text != "SOME DEFAULT TEXT")
{
String persentContentWithDefaultString = t.Text as string;
tb.Text = persentContentWithDefaultString[0].ToString();
// set cursor position
tb.Select(1, 0);
tb.GotFocus -= TextBox_GotFocus;
}
}
Actully in my page , there were two textbox and one button. [Username,pass,and click button]. By default , focus goes to my first textbox and User was not able to see the default text.