Hello,
I find it very complicated to work on ListView (details). I am trying a simple thing to add items in a ListView and update the sub items on a timer event.
If I add Items in ListView during form load, then the sub items added later don’t get updated at all though I do SubItems.Clear();
Then I did it other way by completely removing all Items by Items.Remove(); and adding them again. Still the sub items don’t get updated. And the ListView become flicker that’s keeps flicking on every timer event. Also the sub item Forecolor doesn’t work.
While doing all this after a while I get this debug message "Collection has reached its maximum capacity".
How do I smoothly update text of each sub item individually, or without making it flicker and with Forecolors?
public ListViewItem Items1 = new ListViewItem("User");
public ListViewItem Items2 = new ListViewItem("Number");
public ListViewItem.ListViewSubItem SubItems1 = new ListViewItem.ListViewSubItem();
public ListViewItem.ListViewSubItem SubItems2 = new ListViewItem.ListViewSubItem();
listView2.Items.Add(Items1); Items2.BackColor = Color.WhiteSmoke;
listView2.Items.Add(Items2); Items1.BackColor = Color.WhiteSmoke;
SubItems1.ForeColor = Color.Blue;
SubItems1.Text = "Username";
SubItems2.Text = "" + Convert.ToString(Number);
SubItems1.SubItems.Remove(lv2Items1);
SubItems2.SubItems.Remove(lv2Items2);
Items1.SubItems.Add(SubItems1.Text, SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
Items2.SubItems.Add(SubItems2.Text, SubItems2.ForeColor = Color.Blue, Color.Empty, Font);
//To update on a timer event
Items1.SubItems.Clear();
Items2.SubItems.Clear();
Items1.Remove();
Items2.Remove();
listView2.Items.Add(Items1); Items2.BackColor = Color.WhiteSmoke;
listView2.Items.Add(Items2); Items1.BackColor = Color.WhiteSmoke;
Items1.SubItems.Add(SubItems1.Text, SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
Items2.SubItems.Add(SubItems2.Text, SubItems2.ForeColor = Color.Blue, Color.Empty, Font);
Thanks
- Moved byTaylorMichaelLMVPThursday, September 17, 2009 1:56 PMWinForms related (From:Visual C# General)
-
| | marked9 Thursday, September 17, 2009 12:56 PM | Hi,
Try calling BeginUpdate and EndUpdate before and after updating a batch of items... if you're updating multiple items this will be faster and likely reduce flicker, but if you do it for one item at a time it will probably be worse.
As for the subitem forcecolour issue, make sure the UseItemStyleForSubItemsproperty of each parent list view item object is set to false... if it's true then the parent item's forecolour property will override the subitem value.
I don't understand why you had to use a timer, it shouldn't be necessary, and probably isn't a good idea. - Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:47 AM
-
| | Yort Thursday, September 17, 2009 9:46 PM | The native ListView control supports its own type of double-buffering, it is quite effective. That's supported by the .NET ListView class but it is turned off by default. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of your toolbox onto a form. using System; using System.Windows.Forms; class MyListView : ListView { public MyListView() { this.DoubleBuffered = true; } }
Hans Passant.- Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:48 AM
-
| | nobugz Saturday, September 19, 2009 6:54 PM |
Hi,
->Items1.SubItems.Clear();
Items2.SubItems.Clear();
This will remove all the subItems. And also clear item1.text.
->how to update suitems without using a timer?
Change the text property of the items is Ok. You can try the following code.
public ListViewItem Items1 = new ListViewItem("User");
public ListViewItem Items2 = new ListViewItem("Number");
public ListViewItem Items3 = new ListViewItem("Tag");
public ListViewItem.ListViewSubItem SubItems1 = new ListViewItem.ListViewSubItem();
public ListViewItem.ListViewSubItem SubItems2 = new ListViewItem.ListViewSubItem();
private void Form1_Load(object sender, EventArgs e)
{
listView2.Items.Add(Items1);
listView2.Items.Add(Items2);
SubItems1.Text = "Username";
SubItems2.Text = "" + Convert.ToString(100);
Items1.UseItemStyleForSubItems = false;
Items1.SubItems.Add(SubItems1.Text, SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
Items2.UseItemStyleForSubItems = false;
Items2.SubItems.Add(SubItems2.Text, SubItems2.ForeColor = Color.Blue, Color.Empty, Font);
Items3.SubItems.Add("Test");
Items3.Name = "Items3";
listView2.Items.Add(Items3);
timer1.Interval = 1000;
timer1.Start();
}
private void button3_Click(object sender, EventArgs e)
{
//Update the items
Items1.Remove();
Items1.SubItems.Clear(); // Clear Items1
Items1.Text = "User1";
Items1.SubItems.Add("Name1");
listView2.Items.Add(Items1);
Items2.SubItems[0].Text = "User2";
Items2.SubItems.Add("Name2", SubItems1.ForeColor = Color.Red, Color.Empty, Font);
}
private void timer1_Tick(object sender, EventArgs e)
{
listView2.Items["Items3"].SubItems[0].Text = System.DateTime.Now.ToString();
}
Best regards,
Ling Wang
Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread. - Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:48 AM
-
| | Ling Wang Wednesday, September 23, 2009 1:18 PM | Hi,
Try calling BeginUpdate and EndUpdate before and after updating a batch of items... if you're updating multiple items this will be faster and likely reduce flicker, but if you do it for one item at a time it will probably be worse.
As for the subitem forcecolour issue, make sure the UseItemStyleForSubItemsproperty of each parent list view item object is set to false... if it's true then the parent item's forecolour property will override the subitem value.
I don't understand why you had to use a timer, it shouldn't be necessary, and probably isn't a good idea. - Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:47 AM
-
| | Yort Thursday, September 17, 2009 9:46 PM | Hello Yort,
Thanks for the reply. I have a timer that updates the actual data, so since the data is updated I try to update the list view with the same timer event, just to make it real time. Let me try your suggestions.
Thanks. | | marked9 Thursday, September 17, 2009 9:54 PM | Ok, that makes sense. Let me know how those other suggestions work out.
| | Yort Thursday, September 17, 2009 9:55 PM | Hello, I tried using BeginUpdate and EndUpdate, that didn't help. The only way Iwas able to update itemsby removing them entirely and re-adding them. That keeps the flicker problem unsolved. Fore color worked with UseItemStyleForSubItemssetting to false. listView2.BeginUpdate();
Items1.SubItems.Clear();
Items2.SubItems.Clear();
Items1.Remove();
Items2.Remove();
listView2.Items.Add(Items1); Items2.BackColor = Color.WhiteSmoke;
listView2.Items.Add(Items2); Items1.BackColor = Color.WhiteSmoke;
Items1.SubItems.Add(SubItems1.Text, SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
Items2.SubItems.Add(SubItems2.Text, SubItems2.ForeColor = Color.Blue, Color.Empty, Font); listView2.EndUpdate();
Thanks
| | marked9 Friday, September 18, 2009 3:10 PM | Do you have some reason why you want to clear your ListView and then re-add all your Items? I think it would flicker less noticeably if you simply re-set the .Text property of the existingItems and SubItems. ~~Bonnie Berent [C# MVP] | | BonnieB Saturday, September 19, 2009 4:18 AM | Hi Bonnie,
I am trying to update the text in sub items. I was trying it by removing and re-adding items and sub items. Now I know the right way to do it, sub items get refreshed just by -
Items1.SubItems[0].Text = "oldtext"; Items1.SubItems[1].Text = "oldtext"; Items1.SubItems[2].Text = "oldtext"; //update Items1.SubItems[0].Text = "newtext"; Items1.SubItems[1].Text = "newtext"; Items1.SubItems[2].Text = "newtext";
This doesn't need BeginUpdate, EndUpdate and re-adding items. Still even this method the flicker problem isn't going away.
Thanks.
| | marked9 Saturday, September 19, 2009 11:45 AM | The native ListView control supports its own type of double-buffering, it is quite effective. That's supported by the .NET ListView class but it is turned off by default. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of your toolbox onto a form. using System; using System.Windows.Forms; class MyListView : ListView { public MyListView() { this.DoubleBuffered = true; } }
Hans Passant.- Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:48 AM
-
| | nobugz Saturday, September 19, 2009 6:54 PM | That is very cool Hans. Thanks for pointing that out ... guess I learned something new today ... and I thought I knew the ListView pretty well. It's too bad it's not a public property (not that it matters to me, since I have almost all UI controls sub-classed anyway).
~~Bonnie Berent [C# MVP] | | BonnieB Saturday, September 19, 2009 8:16 PM | Hans & Bonnie thank youfor this reply. Hans, I added a class as you mentioned, then complied and replaced the old list view with a new one.Still the flicker problem is intact. I am not sure if this right, I also placed the items and sub iteams in MyListView class.Now I wantthe text of SubItems to update in realtime (in background, the source of the sub items' text is a structurethat gets updated using a timer), I am trying to update thetext using the same timer event. I guess the flickering won't go away unless the text is updated outside of the timer event. If thats the case then I have re-word my question, how to update suitems without using a timer?
class myListView : ListView
{
public static ListViewItem Items1 = new ListViewItem("User");
public static ListViewItem Items2 = new ListViewItem("Number");
public static ListViewItem.ListViewSubItem SubItems1 = new ListViewItem.ListViewSubItem();
public static ListViewItem.ListViewSubItem SubItems2 = new ListViewItem.ListViewSubItem();
public myListView()
{
this.DoubleBuffered = true;
}
}
//in form load
listView2.Items.Add(myListView.Items1); myListView.Items2.BackColor = Color.WhiteSmoke;
listView2.Items.Add(myListView.Items2); myListView.Items1.BackColor = Color.WhiteSmoke;
myListView.Items1.SubItems.Add(myListView.SubItems1.Text, myListView.SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
myListView.Items2.SubItems.Add(myListView.SubItems2.Text, myListView.SubItems2.ForeColor = Color.Blue, Color.Empty, Font);
//in timer event myListView.Items1.SubItems[0].Text = "newtext"; myListView.Items1.SubItems[1].Text = "newtext"; myListView.Items1.SubItems[2].Text = "newtext";
Thanks
| | marked9 Monday, September 21, 2009 8:55 PM |
Hi,
->Items1.SubItems.Clear();
Items2.SubItems.Clear();
This will remove all the subItems. And also clear item1.text.
->how to update suitems without using a timer?
Change the text property of the items is Ok. You can try the following code.
public ListViewItem Items1 = new ListViewItem("User");
public ListViewItem Items2 = new ListViewItem("Number");
public ListViewItem Items3 = new ListViewItem("Tag");
public ListViewItem.ListViewSubItem SubItems1 = new ListViewItem.ListViewSubItem();
public ListViewItem.ListViewSubItem SubItems2 = new ListViewItem.ListViewSubItem();
private void Form1_Load(object sender, EventArgs e)
{
listView2.Items.Add(Items1);
listView2.Items.Add(Items2);
SubItems1.Text = "Username";
SubItems2.Text = "" + Convert.ToString(100);
Items1.UseItemStyleForSubItems = false;
Items1.SubItems.Add(SubItems1.Text, SubItems1.ForeColor = Color.Blue, Color.Empty, Font);
Items2.UseItemStyleForSubItems = false;
Items2.SubItems.Add(SubItems2.Text, SubItems2.ForeColor = Color.Blue, Color.Empty, Font);
Items3.SubItems.Add("Test");
Items3.Name = "Items3";
listView2.Items.Add(Items3);
timer1.Interval = 1000;
timer1.Start();
}
private void button3_Click(object sender, EventArgs e)
{
//Update the items
Items1.Remove();
Items1.SubItems.Clear(); // Clear Items1
Items1.Text = "User1";
Items1.SubItems.Add("Name1");
listView2.Items.Add(Items1);
Items2.SubItems[0].Text = "User2";
Items2.SubItems.Add("Name2", SubItems1.ForeColor = Color.Red, Color.Empty, Font);
}
private void timer1_Tick(object sender, EventArgs e)
{
listView2.Items["Items3"].SubItems[0].Text = System.DateTime.Now.ToString();
}
Best regards,
Ling Wang
Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread. - Marked As Answer byLing WangMSFT, ModeratorFriday, September 25, 2009 2:48 AM
-
| | Ling Wang Wednesday, September 23, 2009 1:18 PM |
|