I'm using a list box where there are on average about 500 thumbnails (items) that can be sorted and searched.
Since I'm using default databinding and search descriptors (which I've heard are slow due to reflection) the list takes a noticeable pause of a few seconds loading, sorting, and searching (the list dynamically updates based on the contents of the search box so the first one or two letters typed are really slow).
I don't think I can fully do away with reflection give the timeframe for the project, and speed isn't super essential, but I'd like some kind of graphical indication of the delay so it doesn't confuse the user. How could I do something like a website video loading screen where the listbox grays out and some kind of loading circle indicates it's processing until the list is ready? Or even just grayed out with the words "Loading..." for a few seconds could work. Any ideas?
Thanks in advance for your help and suggestions!!!
Silverlight-Controlkit comes with a very handy "busyindicator"-control... too bad there seems to be no such thing for WPF by default.
But I found this seemfully comparable control for you:
http://sweux.com/blogs/pombeiro/index.php/2009/12/01/a-busy-state-indicator-attached-behavior/
download-source:
http://gallery.expression.microsoft.com/en-us/BusyIndicator
Like Veer wrote, BackgroundWorker is probably your best bet.
For the graphical indication of progress and/or delay, take a look at
http://www.codeproject.com/KB/WPF/WPF_Loading_Wait_Adorner.aspx
It looks like pretty much exactly what you want to do.
Try BackgroundWorker
Use the DoWork method to update your list dynamically based on the search keyword
Use the ProgressChanged method to update your UI with some animation saying 'Loading'. A ProgressBar could be used
Use Dispatcher to access your list inside the DoWork method
Related
I know this is a stupid question, I need to let you guys know that I am fully aware that it is useless in 99% of situations to make a listbox with this many elements in c#:
That being said I need this to be done...is there any way to populate a listbox with 40000 elements without it completely destroying performance/freezing up, thanks!
note: I have tried it, this is per the exact requirements of a professor...when adding 40000 elements through a DataSource and DataBind the application freezes up
You tell me.
for(i=0;i<40000;i++)
{
listBox1.Items.Add("click me");
}
Even if is possible (I never tried it), the usability for this form will be 0.
In that cases a more usable implementation is via lookup text-boxes and lists, where the user can enter a text to search record that matches this text and displays them in a any kind of list.
It is of course possible to do it, but not very practicable.
When using a desktop technology like WinForms or WPF, for a large number of items like this you are better off using something like an auto complete textbox, and have it set to filter/search after the user has typed two or three characters. In this case you can also use a control that offers scrolling virtualisation - this means that there is only a limited number of UI elements created in the scrolling portion of the dropdown, and those elements get reused when a scroll occurs. If you don't use virtualisation then a new element gets created for every list item that gets scrolled in to view. (Note that Silverlight controls have this functionality - just in case it's an option).
For ASP.NET though I would suggest that you do not want to do anything that would cause a large transfer of data (large items, or small items but lots of them) as it won't be performant. Instead you should look to do what Google does - retrieve search results in a paged fashion.
is there any way to make winforms listView showing data like treeView. i mean to make it verticaly oriented and to show columnHeaders one under another and not to put them in horizontal line?
thanx for assistance
Consider using this open-source ObjectListView.
It's a mature control that can show all sorts of lists, a tree-list and much much more (not my code - I'm just a happy user).
It take a few minutes to get used to the idea of using it, but once you got it - using it is a breeze.
Examples:
You can also consider using Better ListView. The usage is 99% same as the original .NET ListView, but it has many extras. For example, every item has a ChildItems property in which you can put further children.
I'm trying to learn WPF and was thinking about creating a simple IRC client. The most complicated part is to create the chat log. I want it to look more or less like the one in mIRC:
or irssi:
The important parts are that the text should be selectable, lines should wrap and it should be able to handle quite large logs.
The alternatives that I can come up with are:
StackPanel inside a ScrollViewer where each line is a row
ListView, since that seems more suitable for dynamic content/data binding.
Create an own control that does the rendering on its own.
Is there any WPF guru out there that has some ideas on which direction to take and where to start?
I suggest you start with a good object model independent of the UI, and then try a multi-line TextBox or a RichTextBox.
Whether these will suffice will depend on exactly how long you want the log to be able to get. If you run into performance issues, you may need to look at virtualization.
First of all, you should consider if you want to select only entire row (like in a listbox), or if you want to select certain characters from a row (like in a textbox).
In the first case, I think a ListView or even a ListBox should be enough, both of them support virtualization when bound to collection and there should be no problem with huge amounts of data. A stack panel inside a ScrollViewer is a little bit like reinventing the wheel for this case and creating a new control is not a very inspired approach in my opinion (as the functionality you want can be achieved with the existing controls, in WPF).
In the second case, if you want to select some text inside of a line, or if you want word wrapping for your longest lines in the log and want to select individual parts of the wrapped lines, then you need to use a control more oriented on displaying text. Kent already suggested a RichTextBox, I would add AvalonEdit control or even the WebBrowser control in which you directly modify its HTMLDocument.
I would suggest to use RichTextBox too, and store items in a log file or database, if you run into performance issues.
Another solution is to use the WPF WebBrowser control and modifiy its HTML content with:
webBrowser.NavigateToString("<HTML><H2><B>This page comes using String</B><P></P></H2></HTML>");
More information about using WebBrowser control
Which control would be best for showing a huge (300.000+) list of filenames?
I've tried DataGridView, but it seems to be overkill and also slow.
Are there better alternatives?
None.
No USER will be able to handle a single list of 300.000+ entries in a meaningful way. Looks like your design is seriously flawed - do you really have to present the complete list?
Consider using a search box and let the users search the file names (use auto completion/suggestions like Google et.al.) or create a separate list for every starting letter (like most address books do). Or find another way to reduce the number of entries from which the user has to select.
The standard ListView control has a virtual mode designed specifically for your situation. I've used it with a million row list previously and it does the job well.
It is a true virtual mode. In other words memory allocation and list population time remains low regardless of the size of the overall list. This is unlike the DataGridView that really starts to slowdown and use memory on large lists.
To use virtual mode set:
VirtualListMode = true
VirtualListSize= 300000
(or whatever size your list currently is)
Then handle the RetrieveVirtualItem event to populate the list on demand from your list. You may also wnat/need to handle the CacheVirtualItems and SearchForVirtualItem events.
Set up pagination and restrict the number of rows displayed by the DataGrid. You can add a combobox to jump between pages. This is a standard solution.
also see this post https://stackoverflow.com/questions/2125963/need-help-in-gridview-and-table
Have you tried the ListView with report style? This is the control used by Windows natively in its file browsers.
Following on from gotch4's answer. Here is a good article from CodeProject on how to do paging with a DataGridView.
You might want to check out ObjectListView, specifically the VirtualObjectListView:
http://objectlistview.sourceforge.net/cs/index.html
I forget off hand what license it has been released under so you might want to look at that before using it in a commercial application.
I've made a custom control, it's a FlowLayoutPanel, into which I put a bunch of other custom controls (just Buttons, each with three Labels and a PictureBox overlayed)
It works ok with around 100 buttons, but bump that up to 1000 and it's in trouble. Bump that up to 5000 and it just dies after 20 seconds.
I have very little custom code, and I make judicious use of suspend and resume layout.
So what am I doing wrong? I'm sure my (fairly rapid) computer should be able to handle a few thousand buttons and labels.
(I'm fairly new to C# GUI stuff, so perhaps I should be doing things completely different anyway.)
Edit 1:
This is pretty much the only custom code at the moment:
flowLayoutPanel1.SuspendLayout();
foreach (DataRow row in dt.Rows) // dt is from a DB query
{
flowLayoutPanel1.Controls.Add(new PersonButton(row));
}
flowLayoutPanel1.ResumeLayout();
and in the PersonButton constructor:
this.label1.Text = row["FirstName"].ToString().Trim() + " "
+ row["Surname"].ToString().Trim();
(There should also be a picture attached but I'm not sure if anyone can see it.)
Edit 2:
I guess I really should be using a DataGridView, or ListView, but I wanted more than just a line of text and a small icon per row; I wanted it to look similar to the downloads view in firefox (Ctrl + J). (See screenshot)
Thanks very much for all your input, BTW. I guess I'll have to rethink...
alt text http://img156.imageshack.us/img156/1057/capture.png
Can a C# WinForm app handle 1000 instances of any type of control? I am no WinForm Guru, but what you are expecting from your application might be unreasonable.
The fact that you want to show 1000+ controls of any type might be a sign that you are approaching the design of your software from the wrong direction.
You'll have to post some of the layout code or we won't be able to help much/at all.
Also, your #1 best bet is to profile your code. Profiling is the only surefire way to find out what exactly is performing slowly in your code. In my experience, this is especially true of UI code.
At 1000+ buttons your probably running perilously low on GDI resources and/or raw handles for your application.
Not sure what your application is supposed to do but a grid or a combo box may be the better option here.
The layout logic required for 5k controls will be too much for any type of wrapping panel. You might want to look into a different type of control designed the hold thousands of entries - something like a DataGridView.
The DataGridView has several different column types available that should work for the type of data you're displaying (images, buttons, labels). Since your database query looks to return a DataTable, you could simply bind that directly to your DataGridView and remove the loop.
It sounds like you seriously need to rethink your interface.
Like others have mentioned, that number of controls on a form will not be usable.
However I have done some experimenting looking at time to create new controls in code, even using reflection, and found that several hundred data-bound controls created on the fly in a flow-layout panel should be created in 1 to 2 seconds.
Posting more code samples may help get a better answer.
More info: I have just rerun my timing test again, 300 controls took 0.5 seconds, 400 took 1.9 seconds, 600 took 3 seconds, 1000 took 6 seconds.
It seems that there is a limit somewhere between 300 and 400 where resources start to get over utilised.
[Necromantic mode = ON]
You have 1000 row of data, but you only can show a few of them, so create only the controls that will be visible, and reuse them changing its content with the new data when you scroll.
Try this; drop this method in your code.
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}