How to make winforms textbox autocomplete correct capitalisation? - c#

Using a winforms textbox with autocomplete set to SuggestAppend I can type out part of a string and the rest will be suggested to me fine.
If a user types "smi" looking for "Smith, John" and then autocompletes the rest of the string by tabbing then the textbox contains "smith, John". But, if the user clicks on the name then the capitalisation is correct.
Is there a way I can get the autocomplete to re-capitalise the user inputted part of the string when the suggestion is accepted by tabbing?
Pressing tab leads to:
Clicking name leads to (this is what I want):

To handle this situation I handled the textbox Leave event. The idea is to split the text by comma, uppercase the first letter of the resulting strings, then join the strings back together.
private void textBox1_Leave(object sender, EventArgs e)
{
string[] strings = this.textBox1.Text.Split(new char[] { ',' });
for (int i = 0; i < strings.Length; i++)
{
strings[i] = string.Format("{0}{1}", char.ToUpper(strings[i][0]), strings[i].Substring(1));
}
this.textBox1.Text = string.Join(",", strings);
}

Here's the function I came up with the end, it replaces the textbox's content with a line from the AutoCompleteCustomSource of the textbox (sorted alphabetically).
So, this will still work for any case (e.g if user entered "aLLeN" it would still correct to "Allen,Charlie (ID:104)"
private void fixContent()
{
String text = txtAutoComplete.Text;
List<String> matchedResults = new List<String>();
//Iterate through textbox autocompletecustomsource
foreach (String ACLine in txtAutoComplete.AutoCompleteCustomSource)
{
//Check ACLine length is longer than text length or substring will raise exception
if (ACLine.Length >= text.Length)
{
//If the part of the ACLine with the same length as text is the same as text, it's a possible match
if (ACLine.Substring(0, text.Length).ToLower() == text.ToLower())
matchedResults.Add(ACLine);
}
}
//Sort results and set text to first result
matchedResults.Sort();
txtAutoComplete.Text = matchedResults[0]
}
Thanks to OhBeWise I attached this to the textbox leave event:
private void txtAutoComplete_Leave(object sender, EventArgs e)
{
fixContent();
}
But also I needed to cover situations when the autocomplete has been accepted which occur when enter, tab, left and right are pressed. Attaching this to the keydown event doesn't work because I think the autocomplete captures the event beforehand, so I attached to the previewkeydown event:
private void txtAutoComplete_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
Keys key = (Keys)e.KeyCode;
if (key == Keys.Enter || key == Keys.Tab || key == Keys.Left || key == Keys.Right)
{
fixContent();
}
}

simple ;
private void textbox_TextChanged(object sender, EventArgs e)
{
AutoCompleteStringCollection a = new AutoCompleteStringCollection();
a = textbox.AutoCompleteCustomSource;
for (int i = 0; i < a.Count; i++)
{
if (a[i].ToLower() == textbox.Text.ToLower())
{
textbox.Text= a[i].ToString();
break;
}
}
}

Related

Filtering WinForms Textbox inputs

So, I have a textbox in my WinForms program, and I want the textbox to only allow answers with at least two dots, and starting with letter "N" or "M".
private void SaveText_Click(object sender, EventArgs e)
{
MainNotifs.Show(this, "Attached !");
attachment = true;
}
I want it to set value of "attachment" to true, only if value of the textbox passes the criteria above.
string input = txtBox.Text;
if((input.StartsWith("N") || input.StartsWith("M")) && input.Count(c => c == '.') >= 2)
{
attachment = true;
}

Autocomplete in windows application

How can i select value in textbox character by character Like HDPOS Autocomplete textbox
I tried
In Page Load
private void loadproductName()
{
DataTable dt = _poshelper.getproductName("Bill_Select_ProductName");
if (dt.Rows.Count != 0)
{
string[] postSource = dt
.AsEnumerable()
.Select<System.Data.DataRow, String>(x => x.Field<String>("UniqueName"))
.ToArray();
var source = new AutoCompleteStringCollection();
source.AddRange(postSource);
txtItemName.AutoCompleteCustomSource = source;
}
}
In Leave
private void txtItemName_Leave(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtItemName.Text))
{
DataSet ds1 = _poshelper.getproductNameExistWhileLeave(txtItemName.Text);
if (ds1.Tables[0].Rows.Count == 0)
{
txtItemName.Text = "";
txtItemName.Focus();
}
else
{
loadLeave(ds1);
txtItemName.Focus();
}
}
}
I need to
If i delete a character using backspace it delete permanently
I need like 2 nd image if i delete mean i need that containt remain in textbox
Update
more clarification, from comments
The String in the textbox it should not be deleted if i press back space Key. Instead it should select each character.Every time i press backspace
Here I'm suggesting changes to make your textbox carry following behavior.
When you don't want "appended suggestion" text (as shown in first image) to be gone when you type backspace in text box,
you can do it these steps
Get Current Textbox text (removed last character as we have back spaced lastly)
Clear Text's Text
Send Text taken text back to textbox
do following change in your code
private void loadproductName()
{
DataTable dt = _poshelper.getproductName("Bill_Select_ProductName");
if (dt.Rows.Count != 0)
{
string[] postSource = dt
.AsEnumerable()
.Select<System.Data.DataRow, String>(x => x.Field<String>("UniqueName"))
.ToArray();
var source = new AutoCompleteStringCollection();
source.AddRange(postSource);
txtItemName.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
txtItemName.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
txtItemName.AutoCompleteCustomSource = source;
}
}
I'm not sure what you are doing in Leave Event. But you can add textBox's KeyUp event, and add code like below in that event.
private void txtItemName_KeyUp(object sender, KeyEventArgs e)
{
// track for backspace
if (e.KeyCode == Keys.Back)
{
if (txtItemName.Text != "")
{
string text = txtItemName.Text.Substring(0, txtItemName.Text.Count() - 1);
txtItemName.Text = "";
txtItemName.Focus();
SendKeys.Send(text);
}
}
}

C# - Arrays - Enter Names and display them

here is my code that works.
1. Except after hitting Show Names button (after entering names) that stored in Array, display textbox scroll bar jump down and have to pull it up to see entered names.
2. Also, after I continue entering names(after entering few), I get line breaks (in show Names textbox) and entered names are shown repeated. It should display the names after the last entered one without repeating the previously entered names and line breaks.
Any ideas what is causing it?
my code:
namespace Arrays
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
//initialize the Array
string[] names = new string[100];
int index = 0;
//Enter Names up to 100 and store them in array
private void btnEnterName_Click(object sender, EventArgs e)
{
if (index < names.Length)
{
names[index++] += txtName.Text;
txtName.Clear();
}
else
{
// array 'full'
}
}
//Display stored Names in Array using foreach loop in multiline textbox
private void btnShowNames_Click(object sender, EventArgs e)
{
txtName.Clear();
foreach (string item in names)
{
txtNames.AppendText(item + Environment.NewLine);
}
}
}
}
For the scrollbar problem, setting the Text instead of using AppendText will resolve the issue:
//Display stored Names in Array using foreach loop in multiline textbox
private void btnShowNames_Click(object sender, EventArgs e)
{
string allNames = "";
foreach (string item in names)
{
allNames += item + Environment.NewLine;
}
txtNames.Text = allNames;
// or more advanced
//txtNames.Text = string.Join(names, Environment.NewLine);
}
Line breaks should happens if you hit the button without entering a name in it. Test the presence of the Text before adding it:
//Enter Names up to 100 and store them in array
private void btnEnterName_Click(object sender, EventArgs e)
{
// remove spaces at start and end
string trimedName = txtName.Trim();
bool nameExist = !string.IsNullOrEmpty(trimedName);
bool notHittingMaxName = index < names.Length;
if (nameExist && notHittingMaxName)
{
names[index++] += trimedName;
txtName.Clear();
}
else
{
// array 'full' or empty name
}
}

Textbox KeyPress Event?

i have textbox only allow decimals and '+'
it allow only 1 Decimal "12.332" i need to allow 1 decimal before '+' and 1 decimal after '+' Example i have 12.43+12.23 i can't type the 12(.) because i allow only 1 decimal i am using Split method to get 2 parts before and after
and it is my code
// checks to make sure only 1 decimal is allowed
if (e.KeyChar == 46)
{
if ((sender as TextBox).Text.IndexOf(e.KeyChar) != -1)
e.Handled = true;
}
And this is My method
if(textBox1.Text.Contains('+')==true )
{
string Value = textBox1.Text;
string[] tmp = Value.Split('+');
string FirstValu = tmp[1];
string SecValu = tmp[0];
}
how to use method with event to allow another decimal place after '+'
I would say use two text boxes like someone said in the comments but if you want to be stubborn here is a function to run inside an event that is called when the text changes in the text box.
void textbox_textChanged(object sender, EventArgs e)
{
string text = textBox.Text;
int pointCounter = 0;
int addCounter =0
string temp = "";
string numbers = "0123456789";
for(int i =0;i<text.Length;i++)
{
bool found = false;
for(int j = 0;j<numbers.Length;j++)
{
if(text[i]==numbers[j])
{
temp+=text[i];
found = true;
break;
}
}
if(!found)
{
if('.' == text[i])
{
if(pointCounter<1)
{
pointCounter++;
temp+=text[i];
}
}else
if('+' == text[i])
{
if(addCounter<1)
{
pointCounter=0;
addCounter++;
temp+=text[i];
}
}
}
}
textBox.text = temp;
}
I would recommend using a Regex to validate your textbox. I would also suggest that using the textbox Validating event would be better than using the Leave event. Here is an example of using a regex in the Validating event:
private void textBox1_Validating(object sender, CancelEventArgs e)
{
TextBox tbox = (TextBox)sender;
string testPattern = #"^[+-]?[0-9]*\.?[0-9]+ *[+-]? *[0-9]*\.?[0-9]+$";
Regex regex = new Regex(testPattern);
bool isTextOk = regex.Match(tbox.Text).Success;
if (!isTextOk)
{
MessageBox.Show("Error, please check your input.");
e.Cancel = true;
}
}
You will find the Regex class in the System.Text.RegularExpressions namespace. Also make sure your textbox has the CausesValidation property set to true.
As an alternative you might also want to look at using the MaskedTextBox Class.

How to get multiple selected items from ListPicker and display them in MessageBox

Here is my code for the list of the items in a ListPicker. What I am trying to do is select one or more options and then after I press submit button I would like to display a MessageBox with the selected Items separated by commas. I also would like to store this value of the items selected to the database but, the first I am trying to do is populate the data into MessageBox.
lstPickerType.Items.Add("Aircrafts");
lstPickerType.Items.Add("Boats");
lstPickerType.Items.Add("Cars");
lstPickerType.Items.Add("Helicopters");
lstPickerType.Items.Add("Electric Powered");
lstPickerType.Items.Add("Gas Powered");
Here is the code that I have got to create a string from the list that is then displayed when the ListPicker is collapsed.
private void lstPickerType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
lstPickerType.SummaryForSelectedItemsDelegate = SummarizeItems;
}
private string SummarizeItems(IList items)
{
if (items != null && items.Count > 0)
{
string summarizedString = "";
for (int i = 0; i < items.Count; i++)
{
summarizedString += (string)items[i];
// if the item is not last coma is added
if (i != items.Count - 1)
summarizedString += ", ";
}
return summarizedString;
}
else
return "Nothing selected";
}
Finally for the button to display the MessageBox i have following code.
private void btnAddLocation_Click(object sender, RoutedEventArgs e)
{
foreach (var item in this.lstPickerType.SelectedItems)
{
var items = new List<object>();
MessageBox.Show(items.ToString());
}
I would really appreciate if anyone could help me to solve this issue. Thank You.
I'm a bit rusty of C#, and i don't have visual studio in this pc, but I would achieve your result without the selectionchanged event in the listpicker.
Trythis code in the button click:
Edit: a cast was missing.
private void btnAddLocation_Click(object sender, RoutedEventArgs e)
{
string r = "";
for (int i=0; i<this.lstPickerType.SelectedItems.Count; i++)
{
r += ((ListPickerItem)this.lstPickerType.SelectedItems[i]).Content;
if (i != this.lstPickerType.SelectedItems.Count - 1)
r += ", ";
}
MessageBox.Show(r);
}

Categories