Advanced item search in combobox C# - c#

I wrote a program with C #
I have a combo box whose items are Binding from the database.I use AutoCompleteMode and AutoCompleteSource to search the combo box.But only when filtering does it find words whose first letter is the same as the input letter.While I need All items that contain these letters displayed.Is there a solution to this problem?

maybe this helps
// Example data
string[] data = new string[] {
"Absecon","Abstracta","Abundantia","Academia","Acadiau","Acamas",
"Ackerman","Ackley","Ackworth","Acomita","Aconcagua","Acton","Acushnet",
"Acworth","Ada","Ada","Adair","Adairs","Adair","Adak","Adalberta","Adamkrafft",
"Adams"
};
public Form1()
{
InitializeComponent();
}
private void comboBox1_TextChanged(object sender, EventArgs e)
{
HandleTextChanged();
}
// Handle Text Box that you Fill
private void HandleTextChanged()
{
var txt = comboBox1.Text;
var list = from d in data
where d.Tolower().Contains(comboBox1.Text.ToLower())
select d;
if (list.Count() > 0)
{
comboBox1.DataSource = list.ToList();
//comboBox1.SelectedIndex = 0;
var sText = comboBox1.Items[0].ToString();
comboBox1.SelectionStart = txt.Length;
comboBox1.SelectionLength = sText.Length - txt.Length;
comboBox1.DroppedDown = true;
return;
}
else
{
comboBox1.DroppedDown = false;
comboBox1.SelectionStart = txt.Length;
}
}

Related

Winforms insert image into ListView / ImageList at index

Winforms, C#, VS2017
ImageList does not have an Insert method (however ListViewItemCollection does). I have tried a few different ways to insert a new image into the middle of a ListView and it's LargeImageList, but not getting it to work quite properly.
Anyone have any tried and true code that works properly?
This is what I have, but the images don't get synced properly to the items in the list.
protected void InsertThumbnail(string key, string keySelected)
{
var newImageList = new ImageList()
{
ImageSize = new Size(thumbWidth, thumbHeight)
};
var itemNew = new ListViewItem();
var foundSelected = false;
//lvAllPages.BeginUpdate();
for (int i = 0; i < lvAllPages.Items.Count; i++)
{
var item = lvAllPages.Items[i];
newImageList.Images.Add(item.Tag.ToString(), lvAllPages.LargeImageList.Images[i]);
if (item.Tag.ToString() == keySelected)
{
var image = batch.GetThumbnail(key);
newImageList.Images.Add(key, image);
itemNew = new ListViewItem()
{
BackColor = Color.Aquamarine,
ImageIndex = i,
Tag = key,
};
if (isLocal)
itemNew.Text = $"{GetFileName(key)} (insert) - {itemNew.ImageIndex}";
foundSelected = true;
}
if (foundSelected)
{
item.ImageIndex = item.ImageIndex + 1;
if (isLocal)
item.Text = $"{GetFileName(item.Tag.ToString())} - {item.ImageIndex}";
}
}
lvAllPages.LargeImageList.Dispose();
lvAllPages.LargeImageList = newImageList;
lvAllPages.Items.Insert(itemNew.ImageIndex, itemNew);
}
One more related thing, but not pertinent to the problems I am having. For anyone looking at this question and having similar issues, this helped with the issue of sorting items after inserting a new one. Default behavior when you insert a new ListViewItem at a given index, it will appear at the bottom of the list. I found this handy class to keep items sorted by index, which solved that problem:
class CompareByIndex : IComparer
{
private readonly ListView _listView;
public CompareByIndex(ListView listView)
{
this._listView = listView;
}
public int Compare(object x, object y)
{
int i = this._listView.Items.IndexOf((ListViewItem)x);
int j = this._listView.Items.IndexOf((ListViewItem)y);
return i - j;
}
}
And in the form load:
lvAllPages.ListViewItemSorter = new CompareByIndex(lvAllPages);
Obviously, that's a design decision. ImageList.Images is a ImageCollection and as such, it implements the IList interface.
Unfortunately, the Insert() method is allowed to throw a NotSupportedException. And that's what the list will do when used like a IList:
((IList)imageList.Images).Insert(5, new Bitmap(10,10));
System.NotSupportedException: 'Specified method is not supported.'
In order to have the images shown in a specific order, use the Add() method which takes the key:
imageList.Images.Add("1", new Bitmap(100,100));
That should also enable you to replace the image:
imageList.Images.RemoveByKey("1");
imageList.Images.Add("1", new Bitmap(200,200));
For that to work, you need to set the Sorting property:
listView1.Sorting = SortOrder.Ascending;
For storing additional information like path etc. use anotther data structure with the same key.
Here's the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ImageList imageList = new ImageList();
Dictionary<string, Metadata> metadata = new Dictionary<string, Metadata>();
private string dir = #"H:\temp";
private void button1_Click(object sender, EventArgs e)
{
// You would set this in the designer, probably
listView1.Sorting = SortOrder.Ascending;
listView1.View = View.LargeIcon;
listView1.LargeImageList = imageList;
// Make sure we start from the beginning
listView1.Items.Clear();
imageList.Images.Clear();
metadata.Clear();
// Add items
for (int i = 0; i < 10; i++)
{
var filename = "1 ("+(i+1)+").png"; // Just strange names I have
var fullFileName = Path.Combine(dir, filename);
imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
metadata.Add(i.ToString(), new Metadata{Path = fullFileName});
listView1.Items.Add(i.ToString(), "Image " + i, i.ToString());
}
// Update view
listView1.Refresh();
listView1.Invalidate();
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 3; i < 6; i++)
{
var filename = "1 ("+(i+2)+").png";
var fullFileName = Path.Combine(dir, filename);
// Change image
imageList.Images.RemoveByKey(i.ToString());
imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
// Match metadata and image
metadata[i.ToString()] = new Metadata{Path = fullFileName};
}
listView1.Refresh();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
var key = listView1.SelectedItems[0].ImageKey;
label1.Text = metadata[key].Path;
}
else
{
label1.Text = "No image selected";
}
}
}
internal class Metadata
{
internal string Path;
}

Looping through labels with similar name C#

I want to change the background of some labels depending on what is written on a text file:
private void Form3_Load(object sender, EventArgs e)
{
string[] words = new string[7];
StreamReader read = new StreamReader(path);
while(!read.EndOfStream)
{
string line = read.ReadLine();
words = line.Split(';');
if(words[6] == "no")
{
//-----What I have to write here---
}
}
read.Close();
}
There are over 50 labels named "lbl101","lbl102","....","lbl150"
try it:
if(words[6] == "no")
{
int count = 150;
for (int a = 1 ; a < count; a++)
{
Label currentLabel = (Label)this.Controls.Find("lbl"+a,true)[0];
//change color of currentLabel
}
}
There's the working solution:
private void Form3_Load(object sender, EventArgs e)
{
int count = 101;
string[] words = new string[7];
StreamReader read = new StreamReader(pathRooms);
while(!read.EndOfStream)
{
string line = read.ReadLine();
words = line.Split(';');
if (words[6] == "no")
{
Label currentLabel = (Label)this.Controls.Find("lbl" + count, true)[0];
currentLabel.BackColor = Color.Yellow;
}
count = count + 1;
}
read.Close();
}
You can iterate all over them using OfType<T>() method on Controls collection of form like:
if(words[6] == "no")
{
foreach(var label in this.Controls.OfType<Label>().Where(x=>x.Name.Contains("lbl")))
{
label.Text = "Some Text";
}
}
This will only work on the labels that are direct child of form, labels nested inside other user controls or nested panels will not be affected, for that you have to do it recursively.
Loop through the Controls collection of the form checking for Label objects. Then, amend accordingly as per the specified value.
1.) Create a List with all the labels.
Label lbl101 = new Label();
Label lbl102 = new Label();
...
List<Label> labels = new List<Label>()
{
lbl101,
lbl102
...
};
2.) If your words[] string is the name of the color you can write:
if(words[6] == "no")
{
System.Drawing.Color myColor = System.Drawing.ColorTranslator.FromHtml(words[..]);
foreach(Label l in Labels)
{
l.BackColor = myColor;
}
}

How to select ListView items programmatically?

I've been looking for a solution since this morning, and even after reading tons of other threads on this subject it doesn't work for me. Without further ados let's check this code sample:
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach( KeyValuePair<int, string> dict in ff_names )
{
ListViewItem lvi = new ListViewItem(dict.Key.ToString());
lvi.SubItems.Add(dict.Value);
listView1.Items.Add(lvi);
}
// Test Item Selection
listView1.Focus();
listView1.Select();
listView1.Items[0].Focused = true;
listView1.Items[0].Selected = true;
string s = listView1.SelectedItems.Count.ToString();
label1.text = s; // sadly, it's equal to 0;
textBox1.Text = listView1.SelectedItems[0].SubItems[0].Text; // program will crash
Technically, I would like to selection an item of the ListView and display one of its element in a textbox. It works when I select an item manually, but when I try to select programmatically like shown above it doesn't want to select anything, the SelectedItems count is equal to zero...
Thank you for you help and hope someone can find a solution to what I'm missing!
Here you go. You'll have to make the event handler for listView1_SelectedIndexChanged.
public Form1() {
InitializeComponent();
listView1.View = View.Details;
listView1.Columns.Add("Key");
listView1.Columns.Add("Value");
LoadListView();
}
private void LoadListView() {
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach (KeyValuePair<int, string> dict in ff_names) {
ListViewItem lvi = new ListViewItem(new string[] { dict.Key.ToString(), dict.Value });
listView1.Items.Add(lvi);
}
// Test Item Selection
listView1.Focus();
listView1.Select();
listView1.Items[0].Focused = true;
listView1.Items[0].Selected = true;
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e) {
if (listView1.SelectedItems.Count > 0) {
label1.Text = (string)listView1.SelectedItems[0].Text; // sadly, it's equal to 0;
textBox1.Text = (string)listView1.SelectedItems[0].SubItems[1].Text;
}
}
I think drankin2112's answer is useful, but you say it doesn't work, so I complement it, hope this could be helpful to you.
To finish your work, you need to do three things as follow:
1.load data and fill in listview;
2.define the process method when listview's selected item changed;
3.give a test method to programmatically select different item, the you can see result.
my sample code is below:
public MainWindow()
{
InitializeComponent();
listView1.View = View.Details;
listView1.Columns.Add("Key");
listView1.Columns.Add("Value");
this.listView1.FullRowSelect = true;
//register the process event
this.listView1.SelectedIndexChanged += this.listView1_SelectedIndexChanged;
//load data
LoadListView();
//test item selection
ToSelectItem(0);
}
void ToSelectItem(int itemIndex)
{
if (itemIndex > listView1.Items.Count - 1)
return;
listView1.Focus();
listView1.Select();
listView1.Items[itemIndex].Focused = true;
listView1.Items[itemIndex].Selected = true;
}
private void LoadListView()
{
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach (KeyValuePair<int, string> dict in ff_names)
{
ListViewItem lvi = new ListViewItem(new string[] { dict.Key.ToString(), dict.Value });
listView1.Items.Add(lvi);
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
label1.Text = (string)listView1.SelectedItems[0].Text; // sadly, it's equal to 0;
textBox1.Text = (string)listView1.SelectedItems[0].SubItems[1].Text;
}
}

calendar column c# in datagridview

Basically I want to show a calendar when I edit some columns in my Datagridview.
Following How to: Host Controls in Windows Forms DataGridView Cells from MSDN I can add wanted kind of column at building.
But in my case, I have to use a datasource provided by an Excel reader which give headings have to be connected to date type columns.
private DataGridView AddCalendars(DataGridView dtgv)
{
dtgv.DataSource = controller.getEmptyDataTable(); // DataTable provided by excel reader
var l = dtgv.Columns.Count;
string[] dateColumns = {"date_received", "date_of_birth"};
for (var i = 0; i < l; ++i)
{
if ( dateColumns.Any( dtgv.Columns[i].HeaderText.Contains )
{
dtgv.Columns[i] = new CalendarColumn(); // this line does not work cause by readonly
}
}
return dtgv;
}
How can I apply Calendar Column control to selected columns ?
Or, how can I obtain same result by building Datagridview different way ?
find an acceptable solution working around this post http://www.codeproject.com/Questions/175124/placing-datetimepicker-in-datagridview
private DateTimePicker cellDateTimePicker;
private List<int> dateColumnsIndexes;
public MainForm()
{
InitializeComponent();
///
this.cellDateTimePicker = new DateTimePicker();
this.cellDateTimePicker.ValueChanged += new EventHandler(cellDateTimePickerValueChanged);
this.cellDateTimePicker.Visible = false;
this.cellDateTimePicker.CustomFormat = "dd/MM/yyyy";
this.cellDateTimePicker.Format = DateTimePickerFormat.Custom;
this.dataGridView1.Controls.Add(cellDateTimePicker);
(...)
}
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
var index = masterDataGridView.CurrentCell.ColumnIndex;
if (this.dateColumnsIndexes.Contains(index))
{
Rectangle tempRect = this.dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
cellDateTimePicker.Location = tempRect.Location;
cellDateTimePicker.Width = tempRect.Width;
try
{
cellDateTimePicker.Value = DateTime.Parse(dataGridView1.CurrentCell.Value.ToString());
}
catch
{
cellDateTimePicker.Value = DateTime.Now;
}
cellDateTimePicker.Visible = true;
}
}
void cellDateTimePickerValueChanged(object sender, EventArgs e)
{
masterDataGridView.CurrentCell.Value = cellDateTimePicker.Value.ToString("dd/MM/yyyy");
cellDateTimePicker.Visible = false;
}
private void AddCalendars(DataGridView dtgv)
{
dateColumnsIndexes = new List<int>();
dtgv.DataSource = controller.getEmptyDataTable(); // DataTable provided by excel reader
var l = dtgv.Columns.Count;
string[] dateColumns = {"date_received", "date_of_birth"};
for (var i = 0; i < l; ++i)
{
if ( dateColumns.Any( dtgv.Columns[i].HeaderText.Contains )
{
dateColumnsIndexes.add(i);
}
}
}

How to store name of dynamic checkbox in an String array

How can store name of dynamically created checkbox in a String array when I don't know how many checkbox will user select at runtime.
Say I have 10 dynamic checkboxes and out of 10 user select 6 checkboxes randomly now how can get the name of those selected checkboxes and store them in a String array.
I know how to use event handler on dynamic check box but confused how to declare Straing array when I don't know what will be be size of an array.
Here what I have done till now -
private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox c = (CheckBox)sender;
//Label myLabel;
String str = null;
if (c.Checked == true)
{
str = c.Text;
gpBox[gpcount] = new GroupBox();
gpBox[gpcount].Name = "gpBox" + Convert.ToString(count);
gpBox[gpcount].Text = str;
gpBox[gpcount].Location = new Point(5, gpposition);
gpBox[gpcount].AutoSize = true;
this.Controls.Add(gpBox[gpcount]);
aCommand3 = new OleDbCommand("select * from batch_tbl where batch_branch LIKE '" + str + "'", main_connection);
aAdapter3 = new OleDbDataAdapter(aCommand3);
ds3 = new DataSet();
aAdapter3.Fill(ds3, "app_info");
ds3.Tables[0].Constraints.Add("pk_bno", ds3.Tables[0].Columns[0], true);
int batch_count = ds3.Tables[0].Rows.Count;
batchCheckBox = new CheckBox[batch_count];
//filling the groupbox with batch code by generating dynamic checkboxes
for (int j=0; j < batch_count; ++j)
{
batchCheckBox[j] = new CheckBox();
batchCheckBox[j].Name = "batch" + Convert.ToString(k);
batchCheckBox[j].Text = ds3.Tables[0].Rows[j][1].ToString();
Console.WriteLine(batchCheckBox[j].Text);
batchCheckBox[j].Location = new System.Drawing.Point(104 * position, 30);
gpBox[gpcount].Controls.Add(batchCheckBox[j]);
batchCheckBox[j].CheckStateChanged += new System.EventHandler(BatchBoxCheckedChanged);
position++;
count++;
Console.WriteLine(batchCheckBox[j].Name);
k++;
}
position = 1;
gpposition += 100;
}
else
{
count--;
this.Controls.RemoveByKey("lbl" + c.Name);
this.Update();
}
}
int total_batch = 1;
string[] batchname;
private void BatchBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox batchBox = (CheckBox)sender;
//Here I want to store name of checkbox in array
if (batchBox.Checked == true)
{
batchname = new String[total_batch];
total_batch++;
}
else
{
}
}
You can try this:
//Gets all checkbox's on the form
List<CheckBox> chks = Controls.OfType<CheckBox>().ToList();
//take only those who is checked, and select only their name property
List<string> names = chks.Where(c => c.Checked).Select(c => c.Name).ToList();
UPDATE
For testing you could print a list of the selected names:
string txt = "";
foreach(string name in names)
{
txt += name+" \n\r";
}
MessageBox.Show(txt);
Thank you everbody
}
list = new List<string>();
}
private void BatchBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox batchBox = (CheckBox)sender;
//Here I want to store name of checkbox in array
if (batchBox.Checked == true)
{
list.Add(batchBox.Text);
}
}
private void button1_Click(object sender, EventArgs e)
{
foreach(string prime in list) // Loop through List with foreach
{
Console.WriteLine(prime);
}
}
This is Done

Categories