Paging data / infinite scrolling on Windows Phone - c#

I want to know is there any other solution of paging data on WindowsPhone Listbox control.
I am used to paging data, by manually checking scrollbar position, and when it reaches the end of screen, then more data is loaded.
I want to ask, is there any other solution (better) of doing this (WP7 or WP8). My solution, which I've mentioned is connected with writing a lot of code (custom events, scroll listener, etc.) I think, there might be an easier solution, as WindowsPhone sdk 8.0 has been released...

The key to WP8 infinite scrolling is LongListSelector control and handling the two events:
ItemRealized (loads item) and ItemUnrealized (removes item).
This events are raised automatically based on the detected static template size(height). It is a completely automatic, on-demand action. The engine "knows" when it should get the new item or remove the old one.
Essential:
You must set the template size manually. Otherwise the count of simultaneously loaded items is unpredictable. For example if you have Image in your template it does not count as space, unless it has specific height.
ContentPresenters of List items seems to recycling. So if you change one item template from code you could magically get the new template for another item to! ;) So... Remember your ItemTemplates and set it on every ItemRealized event if you need two or more.
Unloading of BitmapImage data is pretty buggy. If you have Image in your item template, you should manually free it cache on ItemUnrealized event. And also destroy and reset binding by setting Image.Source to null. And set the original source BitmapImage to new small-sized source with minimal decodepixelwidth/height (you can't null it). I found it is the only way to fight the memory leaks. Here is the details https://stackoverflow.com/a/14225871/1449841
Binded collection for data virtualization could be as big as you want (million is ok). So you should bind that collection once and your only business will be loading and unloading items data by mentioned events.

You can use the VisualStatesGroups that are HorizontalCompression and VerticalCompression, so that you're able to detect when you're around the bottom of a ListBox.
This has been around since Mango so isn't a new WP8 feature, but definitely sounds better than your current solution of "hacky" event handlers.
Read about it on MSDN Blog - "Windows Phone Mango change, Listbox: How to detect compression(end of scroll) states ?"
If you're not avert to changing the control, there is LongListSelector, found in the Windows Phone Toolkit (note this is native in WP8) which may certainly be a better way to approach the problem, it's mentioned in the linked article that this is the new way to do what the old article got at for Mango.

Related

UserControl content not updating

I'm creating a simple UWP application for myself and stuck with lack of understanding of how binding and all that stuff works. Don't know how to explain it better So I created a simple example: https://gist.github.com/anonymous/744dc688d0663a3c14b7a2fc424316f8
The program has a list of selectable items on main screen. I can select several items, press a button and program will show new floating panel, with selected items (And I do further management of these items in my original program). I want this panel to be separate control because my MainPage is already overfilled with code.
The problem is. When I click on the button first time - it works as I expect. But then, when I change selected items and click button again, it shows panel with items from first selection.
My question is - how to do make it work? I have a feeling that it has to be something with INotifyPropertyChanged but cannot understand it.
And I also would be glad to hear the overall recommendations. I'm not c# developer. I'm actually sys. admin but I know a little of python and I learned Delphi 7 in university. So I'm kind of learning c# in process of creation of this application.
UPD: If I change line 28 of SelectedItemsView.xaml from
ItemsSource="{x:Bind SelectedItems}"
To
ItemsSource="{Binding SelectedItems, ElementName=SelectedItemsViewRoot}"
(and add x:Name="SelectedItemsViewRoot" to user control attributes). It works as needed. So new question arrives - is this correct way to do this? I though that Binding is kind of legacy and x:Bind is newer approach that should be used in new apps.
It's ok to use {Binding}, but if you want to stick with {x:Bind}, you can do this with OneWay mode (instead of default OneTime). For example: {x:Bind SelectedItems, Mode=OneWay}.
I strongly encourage you to read these two official tutorials:
Data binding overview and Data binding in depth.
In short, {Binding} is not legacy. It's actually a bit more flexible, but it's performed in runtime, while {x:Bind} is perfmormed at compile time, thus a bit more performant.

Extremely slow performance with multiple user controls

I've put together a scheduling application similar in style to that found in outlook, however it can show the schedules of multiple people. I have written a user control, basically a Border with gradient filled background & TextBlock. One of these controls are added to a Canvas at a set location for every appointment. The trouble is, I will have multiple users, with multiple appointments and may need to display 1000 or so appointments at a time. Initially, it takes an absolute age to instantiate all of these objects, however, I can live with this.
Unfortunately, the big problem arises when I try to scroll through the appointments. I have a couple of buttons to scroll left and right and upon clicking these, the UserControls' Left position are moved left or right a certain number of pixels - it can take several seconds between clicking a button and repainting(I also tried with labels just to test, but it was the same).
I guess the real question here is how to implement an interface, showing hundreds of controls with adequate performance and if this isn't achievable, how would I approach such an UI.
One possible option is a TextBlock CustomControl. You can get the exact same style as you have in your usercontrol but with a somewhat faster loading time.
Without a good, minimal, complete code example that reliably reproduces the problem, it will be difficult if not impossible to completely understand the performance problem you are having, never mind provide a solution.
That said, from your description it sounds like you are really looking to present the user with some type of ItemsControl, such as ListBox or ListView (a specialization of ListBox). In an ItemsControl, you can specify an ItemTemplate that defines how each item in the list will appear; this is analogous to the UserControl you apparently are using now.
I believe it's likely it will work fine just with that change alone. I.e. define your per-item visual as a DataTemplate instead of a UserControl, and set the ItemTemplate property of e.g. your ListBox to that template, then just bind your collection of appointment objects to the ListBox.ItemsSource property.
Note that the ListBox class already defaults to using VirtualizingStackPanel in its ItemsPanel template. So you should have no performance problems at all with this approach if you use ListBox.
If you want to use a different ItemsControl or create a custom one, you may or may not find that you need to use a virtualizing panel object explicitly (such as the VirtualizingStackPanel that ListBox uses). With just 1000 items in the list, even a non-virtualized panel may be fine, but if not then even when not using ListBox, you can always specify it explicitly.

wpf listbox with < 10k entries... how do i make it effiecient?

iphone has 10 listbox entries at a time, it doesnt' load all 10k entries and scroll them all at the same time. it adds one entry, and subtracts one entry at a time. so how do you do this in a wpf listbox? how do i make, say 20 listbox entries, and add one or two, and subtract the same amount? does data binding the listbox take care of this performance issue?
What you are looking for is the VirtualizingStackPanel. This control will only display the items you actually need on screen, even if you have thousands more that are available to the item. Here is the MSDN article about it:
http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx
Here is a small article about this control that explains it simply:
http://windowsclient.net/blogs/microsoft_kc/archive/2009/05/13/what-is-virtualizing-stackpanel.aspx
One key point in this second article is that you should use the Recycling property to make sure you use the least amount of resources like so:
VirtualizingStackPanel.VirtualizationMode="Recycling"
The ListBox WPF control uses a VirtualizingStackPanel by default, unless you change the ScrollViewer.CanContentScroll property false, in which case you get smooth scrolling in exchange for a loss of virtualization.

WPF (irc) chat log control

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

Windows Forms Control - Huge list of filenames

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.

Categories