I am able to implement the autocomplete textbox search, but its case sensitive. i want to make it sase insensitive. I have put an or condition but it checks for first entered letter only. i want the search to be fully case insensitive.
Below is my code
public partial class Form1 : Form
{
AutoCompleteStringCollection acsc;
public Form1()
{
InitializeComponent();
acsc = new AutoCompleteStringCollection();
textBox1.AutoCompleteCustomSource = acsc;
textBox1.AutoCompleteMode = AutoCompleteMode.None;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
acsc.Add("Sim Vodafone");
acsc.Add("sim vodafone");
acsc.Add("sIm");
acsc.Add("siM");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
string d = null;
listBox1.Items.Clear();
if (textBox1.Text.Length == 0)
{
hideResults();
return;
}
foreach (String s in textBox1.AutoCompleteCustomSource)
{
d = textBox1.Text.ToUpper();
if (s.Contains(d) || s.Contains(textBox1.Text))
{
Console.WriteLine("Found text in: " + s);
listBox1.Items.Add(s);
listBox1.Visible = true;
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Text = listBox1.Items[listBox1.SelectedIndex].ToString();
hideResults();
}
void listBox1_LostFocus(object sender, System.EventArgs e)
{
hideResults();
}
void hideResults()
{
listBox1.Visible = false;
}
}
}
I think the only thing, that's missing to convert the string in you autoCompleteSource to upper. Change
d = textBox1.Text.ToUpper();
if (s.Contains(d) || s.Contains(textBox1.Text))
{
Console.WriteLine("Found text in: " + s);
listBox1.Items.Add(s);
listBox1.Visible = true;
}
to
d = textBox1.Text.ToUpper();
string upperS = s.ToUpper();
if (upperS.Contains(d))
{
Console.WriteLine("Found text in: " + s);
listBox1.Items.Add(s);
listBox1.Visible = true;
}
and it should work. Although I am sure, that there should be a simplier solution to autocomplete, than creating your own listbox.
Can you try this.
d = textBox1.Text;
if (s.Contains(d.ToUpper()) || s.Contains(d.ToLower()) || s.Contains(textBox1.Text.ToUpper()) || Contains(textBox1.Text.ToLower()))
Related
First of all I'm sorry for the bad title. I'm a beginner so I don't have the vocabulary to accurately express what I need help with within one sentence.
I am currently trying to program a calculator. The calculator looks like this:
All of the buttons in the left area are working perfectly, but I'm having trouble coding for the buttons on the right. The program works by simply taking the string in the display and calculating it, but that doesn't work with the buttons on the right. For example I want the display to show √x and calculate the answer by using Math.Sqrt(x) when the user presses the √-button, I don't want the display to show Math.Sqrt(x).
My code looks like this:
public partial class Calculator : Form
{
String mathOperator;
public Calculator()
{
InitializeComponent();
}
private void number_Click(object sender, EventArgs e)
{
if (tbxDisplay.Text == "0")
{
tbxDisplay.Clear();
}
Button btnNumber = (Button)sender;
tbxDisplay.Text = tbxDisplay.Text + btnNumber.Text;
}
private void btnClear_Click(object sender, EventArgs e)
{
tbxDisplay.Text = "0";
}
private void operator_Click(object sender, EventArgs e)
{
Button btnOperator = (Button)sender;
mathOperator = btnOperator.Text;
if ((btnOperator.Text == "(" ) && tbxDisplay.Text == "0")
{
tbxDisplay.Clear();
tbxDisplay.Text = tbxDisplay.Text + btnOperator.Text;
}
else
{
tbxDisplay.Text = tbxDisplay.Text + btnOperator.Text;
}
}
private void btnCalculate_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
var v = dt.Compute(tbxDisplay.Text, "");
string answer = v.ToString();
answer = answer.Replace(',', '.');
if (answer.Contains(".0"))
{
answer = answer.TrimEnd('0');
if (answer.EndsWith("."))
answer = answer.TrimEnd('.');
}
tbxDisplay.Text = answer;
}
private void btnDelete_Click(object sender, EventArgs e)
{
if (tbxDisplay.Text.Length > 0 && tbxSDisplay.Text.Length != 1)
{
tbxDisplay.Text =
tbxDisplay.Text.Remove(tbxDisplay.Text.Length - 1, 1);
}
if (tbxDisplay.Text.Length == 1)
{
tbxDisplay.Text = "0";
}
}
private void btnBack_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1();
form1.Show();
this.Hide();
}
private void btnPi_Click(object sender, EventArgs e)
{
tbxDisplay.Text = tbxDisplay.Text + "3.14159265359";
//this is my solution for now
//but as you can see it's very ugly
}
}
I'm trying to use autocomplete. The input text comes from a custom made keyboard, made from a form.
I tried autocomplete feature from a simple textbox and text input from my keyboard and works fine. But when I input text from the custom keyboard, it doesn't work. The custom keyboard adds the input from a key listener Key_Click.
I tried adding an extra 'a' and adding the text as txtInput.Text += 'o'; but it didn't work.
Any ideas?
keyboard code:
public partial class frmTextInput : Form
{
public string input_Text { get; set; }
public frmTextInput(string TEXT,bool CTRL)
{
InitializeComponent();
AlternarTeclas(chkShift.Checked);
AgregarListenerTeclas();
var source = new AutoCompleteStringCollection();
List<string> box = Data.Data.SourcePatente();
foreach (var item in box)
{
source.Add(item);
}
txtInput.AutoCompleteCustomSource = source;
txtInput.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
txtInput.AutoCompleteSource = AutoCompleteSource.CustomSource;
}
private void btnSpace_Click(object sender, EventArgs e)
{
txtInput.Text = txtInput.Text + " ";
}
private void btnBorrar_Click(object sender, EventArgs e)
{
string str = txtInput.Text;
if (!string.IsNullOrEmpty(str))
{
txtInput.Text = str.TrimEnd(str[str.Length - 1]);
}
}
private void btnVolver_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnEnter_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
input_Text = txtInput.Text;
}
private void frmTextInput_Load(object sender, EventArgs e)
{
}
private void chkShift_CheckedChanged(object sender, EventArgs e)
{
AlternarTeclas(chkShift.Checked);
}
private void Key_Click(object sender, EventArgs e)
{
string key = sender.ToString();
if (chkShift.Checked)
{
key = key.ToUpper();
}
else
{
key = key.ToLower();
}
txtInput.Text = txtInput.Text + key.Substring(key.Length - 1);
}
private void AgregarListenerTeclas()
{
foreach (Control c in tabCaracteres.Controls)
{
if (c.GetType() == typeof(Button))
{
if (c.Text.Length == 1 && c.Text != "←")
{
c.Click += Key_Click;
}
}
}
foreach (Control c in tabSymbol.Controls)
{
if (c.GetType() == typeof(Button))
{
if (c.Text.Length == 1 && c.Text != "←")
{
c.Click += Key_Click;
}
}
}
}
private void AlternarTeclas(bool estaShiftApretado)
{
if (estaShiftApretado)
{
foreach (Control c in tabCaracteres.Controls)
{
if (c.GetType() == typeof(Button))
{
if (c.Text.Length < 2)
{
c.Text = c.Text.ToUpper();
}
}
}
}
else
{
foreach (Control c in tabCaracteres.Controls)
{
if (c.GetType() == typeof(Button))
{
if (c.Text.Length < 2)
{
c.Text = c.Text.ToLower();
}
}
}
}
}
private void btnSymbol_Click(object sender, EventArgs e)
{
tabTeclado.SelectTab(tabTeclado.SelectedIndex + 1);
}
private void btnTecAlfanumerico_Click(object sender, EventArgs e)
{
tabTeclado.SelectTab(tabTeclado.SelectedIndex - 1);
}
private void button1_Click(object sender, EventArgs e)
{
txtInput.Text += 'o';
}
}
txtInput.AutoCompleteCustomSource = source;
txtInput.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
txtInput.AutoCompleteSource = AutoCompleteSource.CustomSource;
This should be put in the designer file of your textbox, not here. Try that, and can you see your textbox text value change when you use the custom keyboard? What I understand is you catch click event for your custom keyboard and change txtInput.Text?
I made it work. First of all, it didn't work with textbox multiline.
Then, the correct way to input new chars was emulate the keyboard:
I was triying in function "Key_Click":
== txtInput.Text = txtInput.Text + key.Substring(key.Length - 1); ==> I don't work
Instead I used:
== txtInput.Focus(); // IMPORTANT
SendKeys.Send(key.Substring(key.Length - 1));
If I have two text boxes on a form, how can I make it so that their text properties are perfectly synced? Similar to what would happen if they both processed the same KeyDown event.
I would do it this way:
textBox1.TextChanged += (s, _) =>
{
if (!textBox2.Focused && textBox1.Text != textBox2.Text)
{
textBox2.Text = textBox1.Text;
}
};
textBox2.TextChanged += (s, _) =>
{
if (!textBox1.Focused && textBox2.Text != textBox1.Text)
{
textBox1.Text = textBox2.Text;
}
};
Basically I'm responding to the TextChanged even on each text box, but making sure that the target text box doesn't have focus and that the text actually has changed. This prevents infinite back-and-forth loop trying to update the text and it makes sure that the current insertion point isn't changed by the text being overwritten.
I would say that you partially answered your own question, have them both assigned to the same TextChanged EventHandler check which textbox has changed then update the Text property of the other one, something like this.
private void textBox_TextChanged(object sender, EventArgs e)
{
if (((TextBox)sender).Equals(textBox1))
textBox2.Text = ((TextBox)sender).Text;
else
textBox1.Text = ((TextBox)sender).Text;
}
Modified Code to Keep Carat Position Synced between the two TextBox's , see if this is what you are wanting.
private void textBox_TextChanged(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
if (tb.Equals(textBox1))
{
if (textBox2.Text != tb.Text)
{
textBox2.Text = tb.Text;
textBox2.SelectionStart = tb.SelectionStart;
textBox2.Focus();
}
}
else
{
if (textBox1.Text != tb.Text)
{
textBox1.Text = tb.Text;
textBox1.SelectionStart = tb.SelectionStart;
textBox1.Focus();
}
}
}
I would simply do as follows:
bool flag1, flag2;
private void t1_TextChanged(object sender, EventArgs e)
{
if (flag2) return;
flag1 = true;
t2.Text = t1.Text;
flag1 = false;
}
private void t2_TextChanged(object sender, EventArgs e)
{
if (flag1) return;
flag2 = true;
t1.Text = t2.Text;
flag2 = false;
}
I made this calculator in C# and I have one problem: When I press keyboard something like 1 it gives me incorrect result double number. I don't get the correct result.
Do you know what I am doing wrong,
Thank you very much!
namespace Calculator
{
public partial class Calculator : Form
{
Double value = 0;
String operation = "";
int i = 0;
bool operation_pressed = false;
bool button_dot = false;
OperationClass class1 = new OperationClass();
public Calculator()
{
InitializeComponent();
this.KeyPreview = true;
this.KeyPress += new KeyPressEventHandler(Calculator_KeyPress);
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void Calculator_Load(object sender, EventArgs e)
{
}
private void Calculator_KeyPress(object sender, KeyPressEventArgs e)
{
if ((result.Text == "0") || (operation_pressed))
result.Clear();
switch (e.KeyChar)
{
// key press from 0-9
case (char)48:
case (char)49:
case (char)50:
case (char)51:
case (char)52:
case (char)53:
case (char)54:
case (char)55:
case (char)56:
case (char)57:
e.Handled = true;
result.Text += e.KeyChar.ToString();
break;
}
}
private void button_Click(object sender, EventArgs e)
{
if ((result.Text == "0") || (operation_pressed))
result.Clear();
operation_pressed = false;
Button b = (Button)sender;
result.Text = result.Text + b.Text;
}
private void operator_click(object sender, EventArgs e)
{
Button b = (Button)sender;
operation = b.Text;
value = Double.Parse(result.Text);
operation_pressed = true;
equation.Text = value + " " + operation;
}
private void buttonCE_Click(object sender, EventArgs e)
{
result.Text = "0";
equation.Text = "";
button_dot = false;
}
private void buttonC_Click(object sender, EventArgs e)
{
result.Clear();
value = 0;
}
private void buttonEqual_Click(object sender, EventArgs e)
{
equation.Text = "";
button_dot = false;
operation_pressed = true;
if (operation != "")
result.Text = class1.GetResult(operation, value, result.Text);
else
result.Text = result.Text + "";
}
private void buttonDot_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
if ((!button_dot && !operation_pressed) || result.Text == "0")
result.Text = result.Text + b.Text;
button_dot = true;
}
}
}
You don't need to append keychar in your result.Text (Assuming result is your TextBox item) as you have written in line result.Text += e.KeyChar.ToString();. That's the line which is doubling your input.
Remove it and it'll work as expected.
I'd change it from keypress to KeyUp instead. That way it only fires as soon as the key is released.
Edit: Check out this info: Difference between the KeyDown Event, KeyPress Event and KeyUp Event in Visual Studio
I have created a code for my combobox, that can search addresses in a very large table on Sql Server with the help of stored procedure (i'm working with Entity framework). My stored procedure returns 10 hits and my code fills the combobox with search results. For doing this I'm using BackgroundWorker.
But here I'm now having big problems:
- although the combobox is filled with my search results, it always has the first item selected. Even if I type in only a letter, the whole text gets selected;
After that searching for the address doesn't work anymore. It searches only among these 10 results and I'm having no idea how to solve this. Here is my whole code, that causes me problems:
public String searchedItem = "";
public delegate void DelegateUpdateComboboxSelection(ComboBox myCombo,string value,int count);
BackgroundWorker m_bgworker = new BackgroundWorker();
static AutoResetEvent resetWorker = new AutoResetEvent(false);
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
BindingList<spIskalnikNaslovi_Result1> m_addresses = new BindingList<SP_Result1>();
void m_bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int count = (int)((object[])e.Result)[0];
string value = (string)((object[])e.Result)[1];
ComboBox myCombo = (ComboBox)((object[])e.Result)[2];
DelegateUpdateComboboxSelection ndelegate = new DelegateUpdateComboboxSelection(UpdateComboSelection);
if (this.InvokeRequired)
{
Invoke(ndelegate, new object[] {myCombo, value, count});
return;
}
else
{
UpdateComboSelection(myCombo, value, count);
return;
}
}
private void UpdateComboSelection(ComboBox myCombo, String value, int count)
{
myCombo = comboBox9;
myCombo.DataSource = m_addresses;
searchedItem = myCombo.Text;
if (count > 0)
{
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
}
public void FillComboboxBindingList(object sender, DoWorkEventArgs e)
{
if (m_bgworker.CancellationPending)
{
resetWorker.Set();
e.Cancel = true;
return;
}
else
{
string value = (String)((Object[])e.Argument)[0];
List<SP_Result1> result;
result = _vsebina.SP_searcher(value).ToList<SP_Result1>();
m_addresses = new BindingList<SP_Result1>();
foreach (SP_Result1 rez in result)
{
if (m_addresses.Contains(rez))
{
continue;
}
else
{
m_addresses.Add(rez);
}
}
foreach (SP_Result1 r in m_addresses.ToArray())
{
if (!result.Contains(r))
{
m_addresses.Remove(r);
}
}
e.Result = new object[] { rezultat.Count, vrednost, null };
return;
}
}
private void comboBox9_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox9.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox9.Text = "";
}
else
{
comboBox9.Text = comboBox9.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox9_Enter(object sender, EventArgs e)
{
comboBox9.SelectionStart = 0;
comboBox9.SelectionLength = 0;
}
private void comboBox9_Click(object sender, EventArgs e)
{
comboBox9.Text = "";
}
private void comboBox9_KeyPress(object sender, KeyPressEventArgs e)
{
Search();
}
public void Search()
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
if (m_bgworker.IsBusy)
{
m_bgworker.CancelAsync();
m_bgworker = new BackgroundWorker();
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
}
m_bgworker.RunWorkerAsync(new object[] { comboBox9.Text, comboBox9 });
}
}
Maybe can someone enlighten me, what I'm doing wrong. This is first time, that I'm using BackgroundWorker. I have no idea, how
to achieve "search as you type" with combobox in any other way, because my datatable with addresses is quite large (million records).
Thanks in advance for any kind of help or code example.
Vladimir
Edit 1:
Ok, here is my code, before I have used BackGroundWorker. It worked, but it searches very very slow (it can take up to 10 seconds):
private void comboBox9_TextChanged(object sender, EventArgs e)
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
FillCombobox(comboBox9.Text, comboBox9);
}
}
public void FillCombobox(string value, ComboBox myCombo)
{
List<spIskalnikNaslovi_Result1> result;
result = _vsebina.spIskalnikNaslovi1(value).ToList();
if (result.Count() > 0)
{
myCombo.DataSource = result;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
return;
}
Is there a way to speed this up without having backgroundworker?
make a button you will call searchbutton
and in click_event of this button call your search() method that run your backgroundworker
that fill the combobox
clear you key_press event of your combobox and it will work
the mistake is you key_press event that call every key stroke happening your search method
so retrieve it
You should get your items in a list, use that list to populate your combobox.
then set AutoCompleteMode property value to Suggest or Append or SuggestAppend and set AutoCompleteSoucre property value to ListItems.
For "Search as you Type", which is actually "Filter as you Type" more than search, you need to implement the OnKeyDown or KeyPressed event.
What you would do is take the search string, which is the current text at the time of the event, then filter the master list using that string. Normally one would use "Starts With" for the filtering, but you could also simply use "Contains". Then you live update the contents of the box with the results from the filter. This is accomplished by changing and refreshing the Datasource.
Here is my final solution without BackGroundWorker. It works quick with my large table, and is upgraded for using a stored procedure on SQL Server (if you use Entity Framework). I use Timer to make sure the user can find a value, that he is searching.
Here you can see the original solution, that I found on this site (thanks to Max Lambertini and algreat for the idea and working concept):
C# winforms combobox dynamic autocomplete
My solution:
private bool _canUpdate = true;
private bool _needUpdate = false;
List<spIskalnikNaslovi_Result1> dataFound;
private void comboBox12_TextChanged(object sender, EventArgs e)
{
if (_needUpdate)
{
if (_canUpdate)
{
_canUpdate = false;
refreshData();
}
else
{
restartTimer();
}
}
}
private void comboBox12_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox12.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox12.Text = "";
}
else
{
comboBox12.Text = comboBox12.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox12_TextUpdate(object sender, EventArgs e)
{
_needUpdate = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
_canUpdate = true;
timer1.Stop();
refreshData();
}
private void refreshData()
{
if (comboBox12.Text.Length > 1)
{
FillCombobox(comboBox12.Text, comboBox12);
}
}
private void restartTimer()
{
timer1.Stop();
_canUpdate = false;
timer1.Start();
}
private void FillCombobox(string value, ComboBox myCombo)
{
dataFound = _vsebina.spIskalnikNaslovi1(value).ToList();
if (dataFound.Count() > 0)
{
myCombo.DataSource = dataFound;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
return;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
return;
}
}