Clearing a treeView crash - c#

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.

Related

Jump n Rows Up or Down in DataGridView on KeyDown or PreviewKeyDown Events

I have trouble implementing arrow key navigation of a DataGridView (no datasource used).
The DataGridView has 2 different type of items, most of the time every second item is of the first type, vice versa the others are of the second type. Now if someone presses KeyUp / Down I want the DataGridView to jump to a row of a given index, not one up or down.
No matter how I try to solve this it is not clear when the event actually ends. If I try this inside the _previewKeyDown method:
if (DgvCarPosAndTrafficMsg.CurrentRow != null)
{
if (e.KeyCode == Keys.Down)
{
if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Ascending)
{
for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i < SessionItems.Count; i++)
{
if (SessionItems[i] is CarPosItem)
{
DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
break;
}
}
}
else
{
for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i > 0; i--)
{
if (SessionItems[i] is CarPosItem)
{
DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
break;
}
}
}
}
else if (e.KeyCode == Keys.Up)
{
if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Descending)
{
for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i < SessionItems.Count; i++)
{
if (SessionItems[i] is CarPosItem)
{
DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
break;
}
}
}
else
{
for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i > 0; i--)
{
if (SessionItems[i] is CarPosItem)
{
DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
break;
}
}
}
}
it would still just jump up or down 1 Row.
I have no clue when this event is actually processed automatically and I would like to have my own behaviour of key up down events. Please help me, DataGridViews in C# and their annoying events are very hard for me to track down. It seems as every event of those grids is processed differently, for some events the new state has already been applied, for others (OnSelectionChanged) it gets processed afterwards. It is documented poorly and not intuitive, I want to avoid / override all of this background stuff.
Ok I found a solution, using only one event method:
Here is my code, it is important to set the evenArgs as handled, and then do your own update method of the grid:
private void DgvCarPosAndTrafficMsg_KeyDown(object sender, KeyEventArgs e)
{
int diffDown;
int diffUp;
if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Descending)
{
diffDown = 1;
diffUp = -2;
}
else
{
diffDown = 2;
diffUp = -1;
}
if (DgvCarPosAndTrafficMsg.CurrentRow != null)
{
if (e.KeyCode == Keys.Down && DgvCarPosAndTrafficMsg.CurrentRow.Index < DgvCarPosAndTrafficMsg.Rows.Count - diffDown)
{
DgvCarPosAndTrafficMsg.CurrentCell = DgvCarPosAndTrafficMsg.Rows[DgvCarPosAndTrafficMsg.CurrentRow.Index + diffDown].Cells[0];
}
else if (e.KeyCode == Keys.Up && DgvCarPosAndTrafficMsg.CurrentRow.Index + diffUp > 0)
{
DgvCarPosAndTrafficMsg.CurrentCell = DgvCarPosAndTrafficMsg.Rows[DgvCarPosAndTrafficMsg.CurrentRow.Index + diffUp].Cells[0];
}
}
e.Handled = true;
DgvCarPosAndTrafficMsg_UpdateAll();
}
I always jump up/down 2 rows as I expect the item of same type there, but in my UpdateAll() method I check again if it has been correct, and correct it if needed, otherwhise (if already correct) I update the visualisation of the data (and fill other grids with details of the selected entry). I hope this will help others too.
You might have -2 and + 2 for both events, I have some treatment going on afterwards so these values are my indexes I needed, adjust this according to your case or give a specific index (as seen in the question)

i would like to make a simple program that prevents the textbox to input duplicate data into the DataGridView

i would like to make a simple program that prevents the textbox to input duplicate data into the DataGridView
here is the error
private void cekId(Kelola kel1)
{
if (txtId.Text == dgvRole.Rows[i].Cells[0].Value.ToString())
{
for (int i = 0; i < dgvRole.Rows.Count; i++)
{
if (txtId.Text == dgvRole.Rows[i].Cells[0].Value.ToString())
{
MessageBox.Show("Data ID Yang Anda Masukkan Sudah Ada Di Dalam DataGrid");
return;
}
}
}
}
Before using i, it should be declared. So as Jonathan Willcock said, you just need to delete the outer if statement.
In addition, need to check if the last line is blank.
If you add data to the DataGridView manually, modify the code like this.
for (int i = 0; i < dgvRole.Rows.Count - 1; i++)
{
if (txtId == dgvRole.Rows[i].Cells[0].Value.ToString())
{
MessageBox.Show("Data ID Yang Anda Masukkan Sudah Ada Di Dalam DataGrid");
return;
}
}
If bind the DataGridView with DataSource, try to set the property AllowUserToAddRows of DataGridView to false.
dgvRole.AllowUserToAddRows = false;

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.

Remove whole ListViewItems except first Column

I want to remove whole ListviewItems in my Listview except first Column. I have got a method but it sometimes throw ArgumentRangeException that i could not find why.
private void ListViewClear()
{
for (int i = 0; i < lstKullanicilar.Items.Count; i++)
{
if (lstKullanicilar.Items[i].SubItems.Count != 1)
{
lstKullanicilar.Items[i].SubItems.RemoveAt(1);
lstKullanicilar.Items[i].SubItems.RemoveAt(2);
lstKullanicilar.Items[i].SubItems.RemoveAt(3);
lstKullanicilar.Items[i].SubItems.RemoveAt(1);
lstKullanicilar.Items[i].SubItems.RemoveAt(1);
}
}
Try somethin like this:
for (int i = 0; i < lstKullanicilar.Items.Count; i++) {
while(lstKullanicilar.Items[i].Count > 1){
lstKullanicilar.Items[i].SubItems.RemoveAt(1);
}
}
The problem with your code is probably that you have a variable amount of items in the SubItems-collection. WIth the code you showed, you must at least have 6 items in the subitems-collection, for not getting an arugment exception.

Programmatically Checking DataBound CheckListBox

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...

Categories