Programmatically Checking DataBound CheckListBox - c#

I have a DataBound "CheckedListBox", I need to check some items on it. I tried with following code...
if (!string.IsNullOrEmpty(search.Languages))
{
string[] langs = search.Languages.Split(',');
for (int i = 0; i < (langs.Length - 1); i++)
{
for (int j = 0; j < clbLang.Items.Count; j++)
{
string lng = clbLang.Items[j] as string;
if (lng.Trim() == langs[i])
{
clbLang.SetItemChecked(j, true);
break;
}
}
}
}
No errors, debuged execution is going through "checking" process, but finally I cannot see anything checked on it.
Then I have added a button and added following code to it. (upon click check all the items)
private void button9_Click(object sender, EventArgs e)
{
for (int i = 0; i < clbLang.Items.Count; i++)
{
clbLang.SetItemChecked(i, true);
}
}
It is "checking" all the items, Please tell me if anyone can see a issue here...?

Finally found out, it is a Bug introduced by MS.
It is well explained here.
The issue is easy to reproduce. Just hide and show a databound
CheckedListBox and you will notice how
the previously checked items get
unchecked.
CheckedListBox SetItemChecked method not working
So we have to find a workaround... I tried follwing way, it is working nice...
At the place where I was calling checking of items I have added following... I am adding what I need to check in Tag of the control.
if (!string.IsNullOrEmpty(search.Languages))
{
clbLang.Tag = search.Languages;
}
Then, following code in that control's "VisibleChanged()" event.
private void clbLang_VisibleChanged(object sender, EventArgs e)
{
string lngs = clbLang.Tag as string;
if (!string.IsNullOrEmpty(lngs))
{
string[] langs = lngs.Split(',');
foreach (string lang in langs)
{
int j = 0;
foreach (DataRowView row in clbLang.Items)
{
if (row != null)
{
string lng = row[1] as string;
if (lng.Trim() == lang)
{
clbLang.SetItemChecked(j, true);
break;
}
}
j++;
}
}
}
}
This works well with me, hope it will benefit you...

Related

Use loop to clear. textBox[i].Clear(). Is this possible?

I am just looking to know this to try and clean up my code, and also for future reference.
I have a number of textBoxes.
tbPart1.Clear();
tbPart2.Clear();
tbPart3.Clear();
tbPart4.Clear();
tbPart5.Clear();
tbPart6.Clear();
tbPart7.Clear();
Is there any way I could use a loop to replace the numbers?
I tried this, but have no idea how i could run the string.
for (int i = 1; i == 7; i++)
{
string p = "tbPart" + i.ToString() + ".Clear";
}
Inside of the form's code (i.e. in a button click event handler), you can enumerate through all of the TextBox controls on the form and perform a specific action on them:
this.Controls.OfType<TextBox>().ToList().ForEach(x => x.Clear());
If you need to only clear some of the TextBox controls, you can provide a sort of filter like so:
this.Controls.OfType<TextBox>()
// Add a condition to clear only some of the text boxes - i.e. those named "tbPart..."
.Where(x=>x.Name.StartsWith("tbPart"))
.ToList().ForEach(x => x.Clear());
No, you cannot do it that way. But you can define an array or list where you put the controls and then clear them. For example:
List<TextBox> textboxes = new List<TextBox>();
textboxes.Add(tbPart1);
textboxes.Add(tbPart2);
textboxes.Add(tbPart3);
...
Then when you want to clear them
foreach (var tb in textboxes)
tb.Clear();
TextBox[] boxes = new [] {
tbPart1,
tbPart2,
tbPart3,
tbPart4,
tbPart5,
tbPart6,
tbPart7
};
for (int i = 0; i < boxes.Length; i++)
{
boxes[i].Clear();
}
i think you should use an array of textbox then you can do a loop depends the count of numbers of textboxes.
foreach(Control ctrl in this.Controls)
{
if(ctrl.GetType() == typeof(TextBox))
{
ctrl.Text = String.Empty;
}
}
Answer number one by using Control name inside panel1
private void button2_Click(object sender, EventArgs e)
{
string currentCtrlName;
for (int i = 0; i < panel1.Controls.Count; i++)
{
currentCtrlName = "textBox" + (i+1).ToString();
panel1.Controls[currentCtrlName].Text = "";
}
}
==================
Answer number one by using Control index as a child inside panel1
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < panel1.Controls.Count; i++)
{
panel1.Controls[i].Text = "";
}
}
==================

How to fix this IndexOutOfBoundsException

My program runs fine, but there is a little problem. When I add new tracks previously existing file to the ListBox, the program experiences an error. The code seems unwilling to do looping in a new file which was added in a different time. Please help me. Thanks ....
public partial class Form1 : Form
{
//...
string[] files, paths;
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
files = openFileDialog1.SafeFileNames;
paths = openFileDialog1.FileNames;
for (int i = 0; i < files.Length - 1; i++)
{
listBox1.Items.Add(files[i]);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = paths[listBox1.SelectedIndex];
}
}
Adil has caught the cause of the problem, but there's a cleaner solution:
foreach (string file in files)
{
listBox1.Items.Add(file);
}
... or even better:
listBox1.Items.AddRange(files);
In fact, I'd go even further still, and get rid of the instance variables files and paths completely. I'd either use a Tuple<string, string> or create a class for the file/class pair. Then you can add each complete data item to listBox1.Items, set the DisplayMember so that the file part is displayed, but when the selected index is changed, fetch the path from the selected item. Then there's no need to mess around with indexes at all.
You are adding one file less then the files exists, When you will access the last
Change
for (int i = 0; i < files.Length - 1; i++)
{
listBox1.Items.Add(files[i]);
}
To
for (int i = 0; i < files.Length; i++)
{
listBox1.Items.Add(files[i]);
}
Edit based on comments by OP
You might be adding the files in listbox more then once by clicking button1. This will add new files in listbox but the arrays will loose previous items in the array and the count in array will become less then the items in listbox.
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear(); //Clear the items of list box to keep the same items in both listbox and in array paths.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
files = openFileDialog1.SafeFileNames;
paths = openFileDialog1.FileNames;
for (int i = 0; i < files.Length ; i++)
{
listBox1.Items.Add(files[i]);
}
}
}
If you want to keep the previous selection then use list instead of arrays as list can grow more easily then the array.
string[] files;
List<string> paths = new List<string>() ;
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
files = openFileDialog1.SafeFileNames;
paths.AddRange(openFileDialog1.FileNames.ToList());
for (int i = 0; i < files.Length; i++)
{
listBox1.Items.Add(files[i]);
}
}
}
I don't think the problem is with adding items to the array. The more likely cause is the SelectedIndexChanged event handler. You should bounds check SelectedIndex to be sure it is valid.
int idx = listBox1.SelectedIndex;
if (paths != null && idx > 0 && idx < paths.Length)
{
axWindowsMediaPlayer1.URL = paths[idx];
}
I think both Jon and Adil are absolutely correct and you can definitely use their code to fix part of the problem. But, my guess is that you don't have any elements in paths and so when you try to get an element from it, it throws you an exception. Can you try the following code:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (paths.Length >= listBox1.SelectedIndex)
axWindowsMediaPlayer1.URL = paths[listBox1.SelectedIndex];
}
See if you're still thrown an exception and if not, then you have another problem of why your paths variable is not being set or why the listbox selected index is greater than the elements in the variable.

on-the-fly search algorithm in listbox

So, I have a listbox with x number of items. On top of the listbox I have a TextBox (this is the search field). I try do develop an algorithm that removes items from the listbox, if it doesn't contain the searchword (variable keyword in the code). This is supposed to happen for each key the user types (on-the-fly). So, the code:
private void _keywordTextBox_TextChanged(object sender, EventArgs e)
{
string keyword = _keywordTextBox.Text;
if (keyword == searchtext || isSpace) // do nothing if space is typed - searchtext is a templatetext in the textbox ("type here to search...")
return; // ignore
else if (keyword == "")
{
listBox.Items.Clear();
foreach (string s in originalList)
listBox.Items.Add(s);
}
else
{
List<string> selection = new List<string>();
foreach (string s in originalList) // originalList is the listbox at startup
selection.Add(s);
listBox.BeginUpdate();
string[] keywordSplit = keyword.Split(' ');
try
{
for (int i = originalList.Count - 1; i >= 0; i--)
{
string[] selectionSplit = selection[i].Split(' ');
int l = 0; // number of hits
for (int j = 0; j < selectionSplit.Length; j++)
{
for (int k = 0; k < keywordSplit.Length; k++)
{
if (selectionSplit[j].ToLower().Contains(keywordSplit[k].ToLower()))
{
l++;
break;
}
}
}
if (l < keywordSplit.Length) // Not hit on all keywords
selection.RemoveAt(i);
}
}
finally
{
listBox.Items.Clear();
foreach (string s in selection) // Add selection in listbox
listBox.Items.Add(s);
if (listBox.Items.Count > 0)
listBox.SetSelected(0, true); // Select first item in listbox
listBox.EndUpdate();
}
}
}
The problem is hard to describe, other than it doesn't work as intended. The behavour is, as far as I can see, sporadic.
If I search for "ck flow", I should get a hit for stackoverflow. More importantly, it should also work if I deletes chars (delete key of backspace). Anybody?
Edit: more details:
The listbox should shrink and grow on each keystroke, based on what the user searches for. The listbox should keep every item that matches the keyword typed in by the user, and filter away that doesn't match.
Or you could try to work out a Regular Expression:
private void textBox1_TextChanged(object sender, EventArgs e)
{
string keyword = textBox1.Text;
if (string.IsNullOrEmpty(keyword.Trim()))
{
listBox1.Items.Clear();
listBox1.Items.AddRange(_originalList.ToArray());
}
else
{
Regex regex = new Regex(GetRegexPatternFromKeyword(keyword));
List<string> selection =
_originalList.Where(s => regex.IsMatch(s)).ToList();
listBox1.Items.Clear();
listBox1.Items.AddRange(selection.ToArray());
}
}
private static string GetRegexPatternFromKeyword(string keyword)
{
string[] words =
keyword.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(word => "(?=.*" + word.Replace(")", #"\)") + ")").ToArray();
return string.Join("", words);
}
disclaimer: there could be some cases where an input would 'destroy' the regex pattern
Your code increases l too often. For instance;
the text 'aaa aaa aaa' with searchword 'aaa bbb' will give an l of 3 because every time you find 'aaa' you increase l. So this will be a match even though 'bbb' is never found.
You can fix this (among others) by deleting found parts of keywordsplit and recreating keywordsplit anew before every search of a new selectionline.
l++;
break;
becomes
l++
keywordSplit.RemoveAt[k];
break;
and move
string[] keywordSplit = keyword.Split(' ');
to just before you start the k loop
Altough I feel there might be better ways to achieve what you want with a bit cleaner and faster code it should work.
I got it to work. #IvoTops helped me in the right direction. Just loop trough all the keyword first, and then the selections.
for (int j = 0; j < keywordSplit.Length; j++)
{
for (int k = 0; k < selectionSplit.Length; k++)
{
if (selectionSplit[k].ToLower().Contains(keywordSplit[j].ToLower()))
{
l++;
break;
}
}
}
Seems to work ok now.

How to access the indexes of all listbox items?

I am creating an application to search the user typed word from list box. I want to Show only that items in listbox which are matched with the character typed by the user. I am unable to find the exact syntax for this.
private void textBox1_TextChanged(object sender, EventArgs e)
{
string a=textBox1.Text;
for (int i = 0; i < listBox1.Items.Count; i++)
{
if(a[0]==listBox1.Items(i).char[0])//how to do this?
{........
}
}
}
if you want to check the char of a do something like this
also if you are not getting the "Text / String Value.. add the .ToString(); after listBox1.Items[i].ToString();
if(a[i]== listBox1.Items[i])
{
//i is the incremented value here..
}
foreach (char valchar in a)
{
// do your logic.. 'X' single quotes for Char
}
if you want to check for a string in a do
foreach (string valString in a)
{
// do your logic for a string check if valString = "X" for example "" double quotes for
}
Like this:
string a = textBox1.Text;
for (int i = 0; i < listBox1.Items.Count; i++)
{
if( a[0] == listBox1.Items[i].Text)
{
//Do Something...
}
}

Clearing a treeView crash

in a c# wpf application, Im loading a treeView from a list, it has a delete, edit, and add button used with information saved in a list from a textFile, it also has a update button which when clicked it clears the treeView and then reloads the textFile info into the list and then the lists into the treeView however whenever i click the update its crashes my file when it hits: treeView1.Items.Clear(); all the variables prior to the .Clear() lines at the start are lists, also the there are more if statements similar to this one if(i == 0) i just took them out cause they all work the same. Thanks
here is the event code for the updated button
private void buttonUpdate_Click(object sender, RoutedEventArgs e)
{
name.Clear();
description.Clear();
dateStart.Clear();
dateDue.Clear();
status.Clear();
priority.Clear();
details.Clear();
using (StreamReader sr = new StreamReader("TaskList.txt"))
{
int i = 0;
while (!sr.EndOfStream)
{
//if its on the first line of a task
if (i == 0)
{
name.Add(sr.ReadLine());
++i;
}
else if (i == 1)
{
description.Add(sr.ReadLine());
++i;
}
else if (i == 2)
{
dateStart.Add(sr.ReadLine());
++i;
}
else
{
details.Add(sr.ReadLine());
i = 0;
}
}
treeView1.Items.Clear();
for (int j = 0; j < name.Count; ++j)
{
TreeViewItem taskTree = new TreeViewItem();
taskTree.Tag = name[j];
taskTree.Header = name[j];
taskTree.Items.Add(description[j]);
taskTree.Items.Add(dateStart[j]);
taskTree.Items.Add(dateDue[j]);
taskTree.Items.Add(status[j]);
treeView1.Items.Add(taskTree);
}
sr.Close();
}
}
After clearing the treeview, SelectedItem is null.

Categories