WPF ComboBox, force input to UpperCase - wpf

I have an editable WPF ComboBox with TextSearchEnabled. I need to force the user's text input to uppercase when they type to filter the ComboBox.
I was thinking of modifying the textbox that is part of the control (named 'PART_EditableTextBox') to set CharacterCasing="Upper", however I can't quite figure out how to do this.
Do I need to use a trigger, or modify the template in some way?

This works and seems like a reasonable solution:
protected void winSurveyScreen_Loaded(object sender, RoutedEventArgs e)
{
(comboBox.Template.FindName("PART_EditableTextBox", cbObservation) as TextBox).CharacterCasing = CharacterCasing.Upper;
}
Ensure that the combobox is not collapsed on loaded otherwise the template will not be found.

IMO, the quicker way is to set the UpdateTrigger to PropertyChanged and, in the data object, uppercase the value when it is updated.

I found that post where the attached property is used. That permit to use that for all of your ComboBox without rewriting the code.

private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Textbox editableTextbox = sender as Textbox;
foreach (char ch in e.Text)
{
if (Char.IsLower(ch))
{
editableTextbox.Text += Char.ToUpper(ch);
e.Handled = true;
}
}
}
or try creating an attached behaviour for the textbox

Related

Winforms- Stop SelectedItem being highlighted without using the style DropDownList

This is about ComboBox used in Winforms. I need to stop the selected item being heighlighted. I know I can get it done if I set the style of the combobox to ComboBoxStyle.DropDownList.
But I'm looking for a solution where I don't have to use that. Instead, at the moment what I have done is using ComboBoxStyle.DropDown.
I don't have any other option, because if I set it to DropDown, I have to deal with some other issue in my code. It's due to something else which I cannot avoid.
Can someone suggest an alternative pls ?
use the following code in your form's Paint event.
private void myForm_Paint(object sender, PaintEventArgs e)
{
comboBox1.SelectionLength = 0;
}
or pass focus to another control in your combo box selected index changed event:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox2.Focus();
}

tab multiple selected lines of wpf textbox c#

I am facing a problem with the text box control in WPF application.
The problem is that when the user selects multilines of the text and then clicks on tab, the selected lines are deleted instead of being indented to the right.
Is there a way to solve this issue?
Appreciate any help.
Thanks
Ahmad
You will need to handle it in the code behind as it is not the default action of a textbox. Many ways you can handle it. You will need to override the PreviewKeyDown and you can set the e.handled to true in order for text to not be overridden.
private void TextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
TextBox tbx = sender as TextBox;
if (e.Key == Key.Tab)
{
tbx.Text = tbx.Text.Insert(tbx.SelectionStart, "\t" + tbx.Text.Substring(tbx.SelectionStart));
e.Handled = true;
}
}
Sadly have to say that you have to implement that functionality, as the tab key was not made for that in the TextBox.

How can I undo a TextBox's text changes caused by a binding?

I have a TextBox to which i bound a string, if i now edit the text manually i will be able to undo those changes via TextBox.Undo(), if however i change the string and the TextBox's text is updated, i cannot undo those changes and the TextBox.CanUndo property will always be false.
I suppose this might have to do with the complete replacement of the text rather than a modification of it.
Any ideas on how i can get this to work?
I was facing the same issue (needed to accept input upon Enter and revert to original value upon Escape) and was able to handle it this way:
Set UpdateSourceTrigger of your TextBox.Text binding to Explicit.
Handle KeyDown event of your TextBox and put the following code in there:
if (e.Key == Key.Enter || e.Key == Key.Escape)
{
BindingExpression be = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty);
if (e.Key == Key.Enter)
{
if (be != null) be.UpdateSource();
}
else if (e.Key == Key.Escape)
{
if (be != null) be.UpdateTarget(); //cancels newly supplied value and reverts to the original value
}
}
I found this solution to be very elegant because it can be used in DataTemplates too. For example in my case I used it to allow in-place editing of ListBox items.
OK, started to leave a comment and realized it was an answer :)
TextBox.Undo() is intended to undo a user's interaction with the text box not a value change in the property it's bound to. A change in the property the text box is bound to will just update the value of the TextBox, this is a different change than a user edit via focus/keyboard. If you need to Undo changes to your bound properties you probably need to investigate adding an Undo/Redo stack to your application.
Assign directly to the TextBox:
textBox.SelectAll();
textBox.SelectedText = newText;
The TextBox will apply the changes to the internal undo stack if they are applied in such a way that they appear to have come from the user, like so:
Clipboard.SetText("NewTextHere");
TextBox.Paste();
It's a terrible workaround, as it kills whatever the user has on the clipboard (the restoring of which is pessimistically discussed here: How do I backup and restore the system clipboard in C#?) but I thought it might be worth having posted nonetheless.
So, I think the ViewModel Undo/Redo article is a good one, but it's as much as about the ViewModel pattern as it is about how to write custom Undo/Redo functionality. Also, in response to confusedGeek, I think there could be examples where undoing changes in your model, not just in your individual controls is appropriate (say you had a textbox and a slider both bound to the sample property, you want to undo a change regardless of which control made it, so we're talking about app level undo instead of control level).
So given that, here is a simple, if not somewhat kludgey example of doing precisely what you ask using a CommandBinding and a simplistic undo stack:
public partial class MainWindow : Window
{
public static readonly DependencyProperty MyStringProperty =
DependencyProperty.Register("MyString", typeof(String), typeof(MainWindow), new UIPropertyMetadata(""));
// The undo stack
Stack<String> previousStrings = new Stack<String>();
String cur = ""; // The current textbox value
Boolean ignore = false; // flag to ignore our own "undo" changes
public String MyString
{
get { return (String)GetValue(MyStringProperty); }
set { SetValue(MyStringProperty, value); }
}
public MainWindow()
{
InitializeComponent();
this.LayoutRoot.DataContext = this;
// Using the TextChanged event to add things to our undo stack
// This is a kludge, we should probably observe changes to the model, not the UI
this.Txt.TextChanged += new TextChangedEventHandler(Txt_TextChanged);
// Magic for listening to Ctrl+Z
CommandBinding cb = new CommandBinding();
cb.Command = ApplicationCommands.Undo;
cb.CanExecute += delegate(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
};
cb.Executed += delegate(object sender, ExecutedRoutedEventArgs e)
{
if (previousStrings.Count > 0)
{
ignore = true;
this.Txt.Text = previousStrings.Pop();
ignore = false;
}
e.Handled = true;
};
this.CommandBindings.Add(cb);
}
void Txt_TextChanged(object sender, TextChangedEventArgs e)
{
if (!ignore)
{
previousStrings.Push(cur);
}
cur = this.Txt.Text;
}
private void SetStr_Click(object sender, RoutedEventArgs e)
{
this.MyString = "A Value";
}
}
And here is the XAML:
<Window x:Class="TestUndoBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Name="LayoutRoot">
<TextBox Name="Txt" Text="{Binding Path=MyString, Mode=TwoWay}" />
<Button Name="SetStr" Click="SetStr_Click">Set to "A Value"</Button>
</StackPanel>
</Window>
In this example the behavior is slightly different than typical TextBox undo behavior because 1) I'm ignoring selection, and 2) I'm not grouping multiple keystrokes into a single undo step, both of which are things you would want to consider in a real app, but should be relatively straightforward to implement yourself.

How to auto cap a textbox

How do I make it so that when a user types letters into a textbox in silverlight that it changes these letters to all capitals? And at the same time still fires all the same events such as keypress.
If you want to avoid code behind or custom controls (preferable), this sort of functionality is available via behaviours.
e.g. this one in the Expression blend Gallery converts any text box to which it is attached into uppercase.
Then is just a matter of drag-drop in Blend or adding the trigger manually in VS2010.
There was no easy way to do it except to use an embedded all caps font. All other ways interfered with how the textbox worked.
The simplest way would be:
private void tb_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = (TextBox)sender;
var caret = tb.CaretIndex;
tb.Text = tb.Text.ToUpper();
tb.CaretIndex = caret;
}
If you wanna save even more performance, handle the LostFocus event instead (which you then don't have to worry about carret position either):
private void tb_LostFocus(object sender, RoutedEventArgs e)
{
var tb = (TextBox)sender;
tb.Text = tb.Text.ToUpper();
}
But if the data is bound to a model/entity I would call the ToUpper() on the bound object property setter / OnPropertyChanged, OnTextChanged or whatever it is in the entity.

Remove select all from combobox WPF

I have combobox in WPF application that when the user clicks on it, it selects all the text. How can I change the behavior of this to when the user clicks it just set the typing cursor like a normal textbox?
Try
<ComboBox IsEditable="True" />
According to Reflector, the ComboBox code contains this:
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
ComboBox box = (ComboBox) sender;
if ((!e.Handled && box.IsEditable) && (box.EditableTextBoxSite != null))
{
if (e.OriginalSource == box)
{
box.EditableTextBoxSite.Focus();
e.Handled = true;
}
else if (e.OriginalSource == box.EditableTextBoxSite)
{
box.EditableTextBoxSite.SelectAll(); // <==
}
}
}
This method is registered for the GotFocus event in the static constructor using the EventManager:
EventManager.RegisterClassHandler(typeof(ComboBox), UIElement.GotFocusEvent, new RoutedEventHandler(ComboBox.OnGotFocus));
So, I think you can only change that behavior by deriving a custom control from ComboBox and override this event registration by your own method which replaces the call to SelectAll() with another method which sets the caret to the correct position. However, I do not know how to set the caret to the click position. You might have to use Reflector on the TextBox to find that...
Seems that I had to solve similar issue.
It's quite tricky, but the way I solved is to set IsEditable to false/true from code, at the same time I set the focus on TextBox.
Not the pretties way but does the job.

Resources