I want to display a very large number of items to my ListBox. So I use binding like this
listBox.ItemsSource = largeList;
My ListBox does use VirtualizingStackPanel, however, I see that it takes very long time to render on the screen.
Is there a more effective way to do this ?
I am not sure if there are realy big data you should display them to user
By the way you could trick it like this :
Make a new timer , on tick event (every 5ms) add less than 5 items
Related
I'm using an iterator to iterate through a Linked List of 90,000 Book Objects. Each of them have titles, ISBNs, authors and prices.
In my GUI, I have a text field, and a button which would display these 90,000 Books.toString() in the text field. The user can search for a book, remove a book, or update fields in the book, so I feel like the user should be able to see all the books and all their fields.
The problem is, this takes way too long, I get the beach ball of death and it never loads. When I change the for loop to 10 or 1000, it works fine. Must be an O(n^2), right?
Or is there some other problem?
Thank you.
#FXML
void refreshListButtonPressed(ActionEvent event) {
listBooksTextArea.clear();
bookbag.myIter.reset();
for(int i = 0; i < 1000; i++) {
listBooksTextArea.appendText(bookbag.myIter.getCurrent().getData().toString() +
"\n");
bookbag.myIter.nextLink();
if(bookbag.myIter.atEnd()) {
listBooksTextArea.appendText(bookbag.myIter.getCurrent().getData().toString()+
"\n");
}
}
}
Ideally, I wouldn't even use a for loop, I'd use while (!bookbag.myIter.atEnd()), but the for loop proves to me the code works and the size or efficiency is the issue.
Your code is inefficient in a couple of different ways:
The TextArea stores the text as a String, which is an immutable object. Consequently, each time you call appendText(...) a new String is created, by copying the existing characters plus the new characters to a new string object. Since the size of the string grows essentially linearly on each iteration, this becomes an O(n^2) operation.
The TextArea creates a UI node for the entire text. UI nodes are generally quite expensive, and here you are creating a huge node to lay out, style, and display all 90,000 lines of text, the vast majority of which are not visible on the screen at any given time.
You can at least partially fix the first by concatenating the string in a StringBuilder, and then setting the text of the TextArea once, though this will not fix the second issue.
The preferred approach here is to use a virtualized control, such as a ListView or TableView. These controls create a limited number of cells (one per row in the case of a ListView, one per column per row in the case of a TableView), essentially creating cells only for the visible data. As the user scrolls around, cells are reused to display new data. This greatly enhances performance.
Additionally, these controls probably allow for a better interaction between your UI and your actual data. Using a TableView, each row would represent a Book object, and each cell in the row a property of that object. If you make your table editable, you can validate changes to each cell, i.e. on a property-by-property basis. Using a text area, you would need to carefully parse the changes to the text to make sure the result was a valid list of books.
I would generally recommend working through a tutorial on TableView, e.g. this one. In brief, create a Book class using JavaFX Properties. Create a TableView<Book> and configure the columns to point to appropriate properties using the setCellValueFactory(...) method. You can make the data editable by supplying, for example, a TextFieldTableCell in the cell factory for the column. Then simply add your Book instances to the table's items list.
I'm having trouble implementing a dynamic pivot control.
What I would like to do, is create an image gallery using the pivot, where you could change the image by swiping.
This works natively with the pivot control by binding it's itemsource on my observable collection to display one image on each pivotitem.
The thing is that this solution takes a lot of memory when my gallery contains more than 10 pictures, as it creates an equal number of pivotitems.
What I tried is initializing my collection with 3 items, the currently displayed one, the previous and the next one, and when the user swipes, I updated my list.
I tried this using the "SelectionChanged" event and also with the gesture listener.. without success so far.
Has anyone ever tried to do this? And if yes, how can I implement it?
I do something similar, but don't use a Pivot control. Download the Silverlight toolkit (http://silverlight.codeplex.com/) and use a GestureListener to catch the swipe action:
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragCompleted="OnDrag"/>
</toolkit:GestureService.GestureListener>
Then in code, you have an event handler that catches the swipe event, and updates the image accordingly. Here is the event handler that I use to change my page:
private void OnDrag(object sender, DragCompletedGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
if (e.HorizontalChange < 0)
{
TurnPagesForward(1);
}
else
{
TurnPagesBackward(1);
}
}
}
If you update the items in your list your binding will be lost, so this will probably not work very well.
What might work is the following (but I have not tested it):
Start with an initial collection with five items.
Make sure you display the third item in the list so that the visible item is in the middle of the list.
When changing the visible page the SelectionChanged event is raised.
If you move to the right the selected index is changed to the fourth element. In this case you remove the first element in the list and add a new fifth element.
If you move to the left you do the opposite and remove the last element in the list.
This should ensure that you always can move back and forth while not removing or adding any visible items.
I am not sure if this will work, but it is worth a try. :-)
Don't do this. Lots of people have tried and it doesn't scale to large numbers of images.
Although it would be really nice if it was possible to use the pivot control to create a simple image navigation control it just isn't practical. You'll need to go the more complicated route of doing this yourself with a different method. (Lots of people have tried different ways. Go with what's best for your needs/experience/preferences.)
To start, I put my info into Core Data and I have my table showing up in Interface Builder. It has 20 atributes that are the same except for the number after them ie. example1, example2, etc. Each of these atributes has 12 items for the user to change with 3 variables each(on,off or random).
I want these choices for the user to change to come up in a new window. I don't want to bind each of these variables by hand! Is there a way to bind the whole window?
And should I use an interface builder plugin and make a master window or make 20 windows or ??? I'm a complete novice, but would like to do this the best way.
It sounds like you just need to change UI labels/column-titles. If so, you can bind the text of the label to either data or an attribute of the controller that configures the label for the current state of the data.
If you have repeating units of data, you can define a cell which is bound to a controller and then use as many instances of the cell as needed. See NSMatrix and related containers.
I have a datagrid with many columns. This makes it pretty wide. Now we want to add more information to the table. Aside from removing or shortening existing columns what are some ways we might be able to add additional information without adding new columnes.
The data we want to add would be one of several values. For example:
Projected
Actual
Other
For other cases when the value was an off/on or true/false we would change the color of the row. In this case that doesn't seem to be a good option.
Another thing we considered is using an icon to indicate the information.
Any other ways this could be done?
A solution i've seen implemented with grid components is to have a column chooser - some sort of popup dialog that lists the columns and you can select which ones you would like to see in the grid. You should be able to invoke this popup by triggering it from the grid, e.g. it might appear as an option when the user right clicks and causes the context menu to appear.
Can you group related information into tabs?
an overflow area? ie a number of fields underneath the table that populate based on the selected row.
or just only show the minimum needed info and the have full details in a popup when doble clicked or something..
1) Popup on row hover
2) Drop open inline in the grid with extra info on row click
One technique I've used in the past was to create a "container" type of class that has its own labels and textboxes, and you can arrange them however you want, then insert this class into a single grid column. You still have to do some tricks on binding multiple controls that are not native "grid column" controls, but should help you along. Then, you can actually have each row a single container control in a single grid column...
You can't add completely new data to a grid without reserving a column to display it. The best solution I've seen is to provide only the essential information in the grid displaying all records, and then create a drilldown view that shows all of the data for one row. The drilldown can either be a new view in the same form, a popup for an additional window, or perhaps a mouseover popup.
I've worked on systems that use all sorts of shortcuts to display every last bit of information on a single page, and I found that it just made everything more confusing and harder to use. "Oh, that little icon there means that <insert something totally unrelated to the icon picture>."
How do I disable particular columns in MSHFlexgrid in VB6.0? I don't want my user to edit the values in a particular column.
I don't think the MSHFlexGrid control allows users to edit its data in the first place. Therefore, in effect, all columns are disabled. Job done :)
In fact, you have to add custom code to enable updating e.g. add an appropriate control (textbox, combo, date picker, etc) that does allow editing, hide it at design time, then at run time detect which grid cell should have focus, move and size the control to fit the cell then make it visible then handle events to validate the input then write the contents back to the recordset...
...or you could purchase a third party control that does all this out of the box. The MSHFlexGrid that ships with VB6 is essentially a cut-down version of VSFlexGrid Pro, which I've used and thought was quite good. It has a different way of handling hierarchical data by creating groups (rather than bands) which is superior, IMO. The best thing that can be said about the MSHFlexGrid is that it is easy to bind to a hierarchical ADO recordset to simply display the results but not good if you want to do nice formatting or make the grid editable. The VSFlexGrid Pro, if you can afford it, has more power e.g. you can create data source classes to handle binding to custom data structures (ships with VB6 examples of this including ADO recordset binding) which would be invaluable IMO if you intend to make your hierarchical grid editable.
'A Shortcut way is here... NOT in a proper way. But you can try
'if you need to lock the first 3 columns please use this code:
msf2=name of MSFlexGrid
Private Sub msF2_EnterCell()
With msF2
If msF2.Col = 0 Or msF2.Col = 1 Or msF2.Col = 2 Then
msF2.Col = 3
End If
End With
End Sub