how to create a custom AutoComplete function like inbuilt Autocomplete function? - c#

i want to create a autocomplete function like inbuilt autocomplete where when we type in combobox's text editor filed a matching suggestion comes out like this:
i don't want to use inbuilt AutoCompleteMode.
i have created a AutoCompleteStringCollection named collection and filled it with my database data.
i really don't know where to start as i am very new to programming and i searched for it all over the internet but found nothing related to it. i am really stuck, please help.
i tried this but i knew it will not work as i want
private void comboBox1_TextChanged(object sender, EventArgs e)
{
foreach(string s in collection)
{
if (s.Contains(comboBox1.Text))
{
comboBox1.Text = s;
}
}
}

You can try the following code to achieve the autocompleted function in the combobox.
private void Form1_Load(object sender, EventArgs e)
{
string[] source = new string[] { "Jack", "Jassie", "Junk", "Jungle" };
comboBox1.AutoCompleteMode = AutoCompleteMode.Append;
comboBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
AutoCompleteStringCollection combData = new AutoCompleteStringCollection();
combData.AddRange(source);
comboBox1.AutoCompleteCustomSource = combData;
comboBox1.Items.AddRange(source);
}
int i = 1;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((this.ActiveControl == comboBox1) && (keyData == Keys.Down))
{
if(i%2!=0)
{
comboBox1.SelectedIndex = comboBox1.FindStringExact(comboBox1.Text);
textBox1.Text = comboBox1.SelectedIndex.ToString();
i++;
return true;
}
else
{
int index = comboBox1.FindStringExact(comboBox1.Text) + 1;
if(index<comboBox1.Items.Count)
{
comboBox1.SelectedIndex = comboBox1.FindStringExact(comboBox1.Text) + 1;
textBox1.Text = comboBox1.SelectedIndex.ToString();
i++;
return true;
}
else
{
return true;
}
}
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
}
Result:

int i = 0;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((this.ActiveControl == comboBox1) && keyData == Keys.Down && i == 0)
{
comboBox1.SelectedIndex = comboBox1.FindStringExact(comboBox1.Text);
comboBox1.SelectAll();
i = 1;
return true;
}
else if((this.ActiveControl == comboBox1) && keyData == Keys.Down && i == 1)
{
if (comboBox1.SelectedIndex < comboBox1.Items.Count -1)
{
comboBox1.SelectedIndex++;
comboBox1.SelectAll();
}
return true;
}
if ((this.ActiveControl == comboBox1) && keyData == Keys.Up && i == 0)
{
comboBox1.SelectedIndex = comboBox1.FindStringExact(comboBox1.Text);
comboBox1.SelectAll();
i = 1;
return true;
}
else if((this.ActiveControl == comboBox1) && keyData == Keys.Up && i == 1 )
{
comboBox1.SelectedIndex--;
comboBox1.SelectAll();
if(comboBox1.SelectedIndex < 0)
{
comboBox1.SelectedIndex = 0;
}
return true;
}
else
{
i = 0;
return base.ProcessCmdKey(ref msg, keyData);
}
}

Related

Change row color in datagridview

I know it's already been written about.
Everything looks very good. But when I move to the right to see the rest of the columns, the rows in DataDridView start blinking very much. I can't solve this.
private void registersDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewRow rowDataGridView = null;
string dataPropertyName;
dataPropertyName = this.registersDataGridView.Columns[e.ColumnIndex].DataPropertyName;
int isApprovedColumnIndex = this.registersDataGridView.Columns[isApprovedColumnName].Index;
int isCancelledColumnIndex = this.registersDataGridView.Columns[isCancelledColumnName].Index;
bool theColorHasBeenSet = false;
if (e.RowIndex >= 0 && e.RowIndex != btregisterDgvRowIndex)
{
rowDataGridView = this.registersDataGridView.Rows[e.RowIndex];
if (this.registersDataGridView.Columns[isCancelledColumnIndex].DataPropertyName == "IsCancelled")
{
if (rowDataGridView.Cells[isCancelledColumnIndex].Value != null && rowDataGridView.Cells[isCancelledColumnIndex].Value.ToString() == "Tak")
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.PaleVioletRed)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.PaleVioletRed;
}
theColorHasBeenSet = true;
}
else
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.Ivory)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.Ivory;
}
}
btregisterDgvRowIndex = e.RowIndex;
}
if (this.registersDataGridView.Columns[isApprovedColumnIndex].DataPropertyName == "IsApproved")
{
if (!theColorHasBeenSet)
{
if (rowDataGridView.Cells[isApprovedColumnName].Value != null && rowDataGridView.Cells[isApprovedColumnName].Value.ToString() == "-")
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.LightGray)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.LightGray;
}
theColorHasBeenSet = true;
}
else if (rowDataGridView.Cells[isApprovedColumnName].Value != null && rowDataGridView.Cells[isApprovedColumnName].Value.ToString() == "Nie")
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.PaleVioletRed)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.PaleVioletRed;
}
theColorHasBeenSet = true;
}
else
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.Ivory)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.Ivory;
}
}
btregisterDgvRowIndex = e.RowIndex;
}
}
}
}
else
{
if (rowDataGridView.DefaultCellStyle.BackColor != Color.Ivory)
{
rowDataGridView.DefaultCellStyle.BackColor = Color.Ivory;
}
}
You're not setting the theColorHasBeenSet here which might cause it to change between Ivory and the next color on your list.
Your code seems to verbose to me, try the following
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex < 0)
return;
var rowDataGridView = this.registersDataGridView.Rows[e.RowIndex];
Color GetBackgroundColor()
{
var isApprovedColumnIndex = this.registersDataGridView.Columns[isApprovedColumnName].Index;
var isCancelledColumnIndex = this.registersDataGridView.Columns[isCancelledColumnName].Index;
if (this.registersDataGridView.Columns[isCancelledColumnIndex].DataPropertyName == "IsCancelled")
{
var strValue = Convert.ToString(rowDataGridView.Cells[isCancelledColumnIndex].Value);
if (strValue == "Tak")
return Color.PaleVioletRed;
}
if (this.registersDataGridView.Columns[isApprovedColumnIndex].DataPropertyName == "IsApproved")
{
var strValue = Convert.ToString(rowDataGridView.Cells[isApprovedColumnIndex].Value);
if (strValue == "-")
return Color.LightGray;
if (strValue == "Nie")
return Color.PaleVioletRed;
}
return Color.Ivory;
}
rowDataGridView.DefaultCellStyle.BackColor = GetBackgroundColor();
}

How can I do an ignore case search (C#)

I'm trying to get an a case-insensitive search to work in C#. Currently my code is:
private void txtSearch_KeyPress_1(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
var query = from o in App.Phonebook
where (o.PhoneNumber.Contains(txtSearch.Text) || o.Department.Contains(txtSearch.Text) || o.Name.Contains(txtSearch.Text) || o.Email.Contains(txtSearch.Text))
select o;
dataGridView.DataSource = query.ToList();
}
else
dataGridView.DataSource = phonebookBindingSource;
}
}
I have tried where (o.PhoneNumber.Contains(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase), but I get the error "No overload for method 'Contains' takes 2 arguments." I don't want to do ToUpper() and ToLower().
Any advice would be appreciated.
There are various approaches.
private void txtSearch_KeyPress_1(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
var query = from o in App.Phonebook
where ((o.PhoneNumber.IndexOf(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) >= 0) || (o.Department.IndexOf(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) >= 0) || (o.Name.IndexOf(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) >= 0) || (o.Email.IndexOf(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) >= 0))
select o;
dataGridView.DataSource = query.ToList();
}
else
dataGridView.DataSource = phonebookBindingSource;
}
}
Alternative you could write an extension method:
public static class MyExtensions
{
public static bool ContainsInsensitive(this String str, string txt)
{
return str.IndexOf(txt, StringComparison.InvariantCultureIgnoreCase) >= 0;
}
}
private void txtSearch_KeyPress_1(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
var query = from o in App.Phonebook
where (o.PhoneNumber.ContainsInsensitive(txtSearch.Text) || o.Department.ContainsInsensitive(txtSearch.Text) || o.Name.ContainsInsensitive(txtSearch.Text) || o.Email.ContainsInsensitive(txtSearch.Text))
select o;
dataGridView.DataSource = query.ToList();
}
else
dataGridView.DataSource = phonebookBindingSource;
}
}

How to create complex filter for DataGrid WPF

I want to create filrer for 4 fields. But I get too many code.
I need filter when just one field choosen or a few (2,3 or 4) fields at the same time. How to create logic for it?
My ugly code:
void ViewSource_Filter(object sender, FilterEventArgs e)
{
if (e.Item is Event evnt)
{
bool selectedModel = filterEventsControl.ComboBoxModels.SelectedIndex != 0 && filterEventsControl.ComboBoxModels.SelectedItem != null;
bool selectedIp = filterEventsControl.ComboBoxIPs.SelectedIndex != 0 && filterEventsControl.ComboBoxIPs.SelectedItem != null;
bool selectedParameter = filterEventsControl.ComboBoxParameters.SelectedIndex != 0 && filterEventsControl.ComboBoxParameters.SelectedItem != null;
bool selectedStatus = filterEventsControl.ComboBoxStatus.SelectedIndex != 0 && filterEventsControl.ComboBoxStatus.SelectedItem != null;
if (selectedModel && !selectedIp && !selectedParameter && !selectedStatus)
{
var model = filterEventsControl.ComboBoxModels.SelectedItem.ToString();
if (evnt.DeviceName == model)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
else if (selectedModel && selectedIp && !selectedParameter && !selectedStatus)
{
var model = filterEventsControl.ComboBoxModels.SelectedItem.ToString();
var ip = filterEventsControl.ComboBoxIPs.SelectedItem.ToString();
if (evnt.DeviceName == model && evnt.Ip == ip)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
...
else
{
e.Accepted = true;
}
}
}
It can be something like this:
bool FilterByName(Event evnt)
{
var model = filterEventsControl.ComboBoxModels.SelectedItem?.ToString();
return evnt.DeviceName == model;
}
bool FilterByIp(Event evnt)
{
var ip = filterEventsControl.ComboBoxIPs.SelectedItem?.ToString();
return evnt.Ip == ip;
}
void ViewSource_Filter(object sender, FilterEventArgs e)
{
...
bool res = true;
if (selectedModel)
res = res && FilterByName();
if (selectedIp)
res = res && FilterByIp();
...
}

Get value of checkbox in Datagridview?

I tried to get value of checked checkbox in DataGridView, so I check if value is true or false:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex != -1)
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if ((bool)dataGridView1.Rows[i].Cells["check"].Value == true)
{
dataGridView1.Rows[i].Cells["check"].Value = false;
}
else
{
dataGridView1.Rows[i].Cells["check"].Value = true;
}
button2.Enabled = (counter > 0);
}
}
}
}
It involks an error in line:
if ((bool)dataGridView1.Rows[i].Cells["check"].Value == true)
Second solution:
if (dataGridView1.Rows[i].Cells["check"].Value == null || (bool)dataGridView1.Rows[i].Cells["check"].Value == false)
{
dataGridView1.Rows[i].Cells["check"].Value = true;
counter++;
}
else
{
dataGridView1.Rows[i].Cells["check"].Value = false;
counter--;
}
The code below works, but sometimes checkbox is not checked
I am doing something really similar in a project of mine,
I am only using OnCellValueChanged instead of CellContentClick.
Here's my working line of code
bool completed = Convert.ToBoolean(dgv.Rows[e.RowIndex].Cells[1].Value.ToString());
What is exactly your error? Did you try to see what .Value was in the debugger ?

Masked TextBox with decimal numbers

In my window application I need masked textbox which accept real decmal numbers.
eg.
1) 1.56
2) 22.34
3) 123.34
4) 12312.34
This all value should be valid.
Can anyone tell me how can I do this?
And ya if anyone have better solution for real decimal numbers, instead of this masked TextBox
than I love to see it.
Thanks...
Instead of using a MaskedTextbox, consider using NumericUpDown instead. It supports System.Decimal numbers which supports most real-set numbers you should be caring about.
The NumericUpDown.DecimalPlaces property supports up to 99 decimal places.
Use a custom control like this one (modify it to fulfill your needs):
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace CustomControls
{
public enum PasteRejectReasons
{
Unknown = 0,
NoData,
InvalidCharacter,
Accepted
}
public class DecimalTextBox : TextBox
{
public const int WM_PASTE = 0x0302;
public event EventHandler<KeyRejectedEventArgs> KeyRejected;
public event EventHandler<PasteEventArgs> PasteRejected;
private bool _DecimalSeparator = false;
private int _Precision;
public new HorizontalAlignment TextAlign
{
get { return base.TextAlign; }
set { base.TextAlign = value; }
}
public int Precision
{
get { return _Precision; }
set { _Precision = value; }
}
public DecimalTextBox()
{
TextAlign = HorizontalAlignment.Right;
Precision = 3;
}
protected override void OnGotFocus(EventArgs e)
{
SelectAll();
base.OnGotFocus(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
bool validate = true;
if (Text.Contains(".") || Text.Contains(","))
{
int indexSep;
string[] split;
string partiDecimal = "";
if (Text.Contains("."))
indexSep = Text.IndexOf('.');
else
indexSep = Text.IndexOf(',');
split = Text.Split(new char[] { ',', '.' });
partiDecimal += split[1];
if (partiDecimal.Length >= Precision)
if (SelectionStart > Text.Length - (partiDecimal.Length + 1))
validate = false;
}
bool result = true;
bool validateKeys = (e.KeyCode == Keys.Enter);
bool numericKeys = (
((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))
&& e.Modifiers != Keys.Shift
&& validate);
bool ctrlA = e.KeyCode == Keys.A && e.Modifiers == Keys.Control;
bool editKeys = (
(e.KeyCode == Keys.Z && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.X && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.C && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.V && e.Modifiers == Keys.Control) ||
e.KeyCode == Keys.Delete ||
e.KeyCode == Keys.Back);
bool navigationKeys = (
e.KeyCode == Keys.Up ||
e.KeyCode == Keys.Right ||
e.KeyCode == Keys.Down ||
e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Home ||
e.KeyCode == Keys.End);
bool decimalSeparator = ((
e.KeyCode == Keys.Decimal ||
e.KeyValue == 190 ||
e.KeyValue == 188)&&
TextLength != 0 &&
SelectionLength == 0);
if (decimalSeparator)
{
if (!_DecimalSeparator)
_DecimalSeparator = true;
else
decimalSeparator = false;
}
if (!(numericKeys || editKeys || navigationKeys || decimalSeparator || validateKeys))
{
if (ctrlA)
SelectAll();
result = false;
}
if (!result)
{
e.SuppressKeyPress = true;
e.Handled = true;
if (!ctrlA)
OnKeyRejected(new KeyRejectedEventArgs(e.KeyCode));
}
else
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == ';' || e.KeyChar == '?')
{
if (!(Text.Contains(",") || Text.Contains(".")))
_DecimalSeparator = false;
e.Handled = true;
}
}
protected override void OnTextChanged(EventArgs e)
{
bool invalid = false;
int i = 0;
foreach (char c in Text) // Check for any non digit characters.
{
if (!(char.IsDigit(c) || c == ',' || c == '.'))
{
invalid = true;
break;
}
if (c == ',' || c == '.')
i++;
}
if (i == 0)
_DecimalSeparator = false;
else if (i > 1)
invalid = true;
if (invalid)
{
Text = "";
return;
}
if (Text.Contains(".") || Text.Contains(","))
{
string charSep = "";
string[] split;
string partiEntier = "";
if (Text.Contains("."))
charSep = ".";
else
charSep = ",";
split = Text.Split(new char[] { ',', '.' });
partiEntier += split[0];
if (partiEntier == "")
Text = "0" + charSep + split[1];
}
base.OnTextChanged(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
PasteEventArgs e = CheckPasteValid();
if (e.RejectReason != PasteRejectReasons.Accepted)
{
m.Result = IntPtr.Zero;
OnPasteRejected(e);
return;
}
}
base.WndProc(ref m);
}
private PasteEventArgs CheckPasteValid()
{
PasteRejectReasons rejectReason = PasteRejectReasons.Accepted;
string originalText = Text;
string clipboardText = string.Empty;
string textResult = string.Empty;
try
{
clipboardText = Clipboard.GetText(TextDataFormat.Text);
if (clipboardText.Length > 0)
{
textResult = (
Text.Remove(SelectionStart, SelectionLength).Insert(SelectionStart, clipboardText));
foreach (char c in clipboardText)
{
if (!char.IsDigit(c))
{
rejectReason = PasteRejectReasons.InvalidCharacter;
break;
}
}
}
else
rejectReason = PasteRejectReasons.NoData;
}
catch
{
rejectReason = PasteRejectReasons.Unknown;
}
return new PasteEventArgs(originalText, clipboardText, textResult, rejectReason);
}
protected virtual void OnKeyRejected(KeyRejectedEventArgs e)
{
EventHandler<KeyRejectedEventArgs> handler = KeyRejected;
if (handler != null)
handler(this, e);
}
protected virtual void OnPasteRejected(PasteEventArgs e)
{
EventHandler<PasteEventArgs> handler = PasteRejected;
if (handler != null)
handler(this, e);
}
}
}

Categories