I have a design question : In a pivot view (three "pages"), I have a lot of bindings. Well, about 12 items in each pivot view (TextBox, Map...).
I realized that these binding were slowing a lot the load of my view. But the binding on the first "page" of my pivot is the only one that needs to be loaded. I can put a progress indicator and load in a thread or something my other data (in fact, the binded data will be set only after an HTTPWebRequest).
How can I tell that to my application ? Like "onLoadPageX: bind items"
Thanks a lot, I don't know if i'm clear
You should be able to add a RoutedEventHandler for the Loaded event of each PivotItem. This event is fired when a particular PivotItem page is loaded; there is also a corresponding Unloaded event for when the page unloads, in case you need to free any resources.
Your question is quite vague but there are lots of options around showing a loading state, defering binding and having lots of controls in a pivot:
If you need to do anything that may take time then do it off the UI thread.
If you're doing something which takes time then you should show an indication to the user that something is happening. This could be a message or animation, depending on the likley time period and the rest of the application.
If your content is highly dependent upon data loaded from the web, be sure to have appropriate timeouts on failing to load the data. Also have useful messages if there is no data connection available.
If your UI is highly dependent on details loaded externally you could look at adding the controls to the UI once you know what you need to display.
If the UI will always have the same controls but different content in them, you could consider data-binding to objects which have placeholder content which is updated when the relevant information is downloaded from the web service.
If you have lots of items in your pivot you should consider defereing the loading of individual items so that you don't load them before they are needed. Only load the data on the items next to the one displayed. This way they appear preloaded to the user but ease the impact on the system.
Related
I am using the normal WPF DataGrid to display some data from a REST feed. The REST feed is paged with a next link that contains the URL for the next set of items. The DataGrid is virtualised by having a custom object that implements the IList interface (not IList), and knows how to fetch missing data from the REST feed.
The issue is that if a user scrolls immediately to the bottom this component must do a bunch of REST requests for each "next" page, causing the GUI to freeze. Of course I could simply put up a "wait" screen, but I would actually be able to show an accurate progress bar.
So to accomplish this I have a progress bar on my application status bar that has visibility set to IsLoading on the data context, which in turn passes this down to the paging object. There is another property LoadedPercentage which shows how much of the required data has been loaded.
The issue is that when I scroll to the end of the screen, it still freezes and shows nothing. I set breakpoints in the code to see if my properties were being accessed and they were all hit at the correct times and showed the correct values. So I deduce from this that the DataGrid itself is somehow stopping the GUI thread from doing any drawing while it waits for the IList object to return the requested object.
So does anyone know of a solution for getting the status bar to show up? I would really rather have the status bar appear and track progress rather than some "loading please wait" screen. Can this be done at all with the built in objects or do we have to purchase some third party grid?
EDIT: It wasn't completely clear to some so I wanted to mention: I am doing virtualisation as described here among other places. It seems that when the DataGrid requests a specific entry it blocks the entire UI painting until it the request completes.
Well, UI is busy fetching data from the REST service. If you don't like the behaviour, you can implement data virtualization.
This post explains more: WPF Datagrid: Lazy Loading / Inifinite scroll
As far I know, there is no "ready" solution in WPF, and it will be little hassle, but it should work with some tweaking.
Implementing your custom IList doesn't sound like it would work, so I am not sure about how to "fix" your solution, and if it's even possible.
I have a Silverlight 5 app with a PivotViewer in it. This is binding with the data source correctly, but I need to force a rebind on the templates without replacing the data source and re-setting the entire control. The results are.... interesting.
We are using a ValueConverter to determine what color a tile should be, and this value converter can be adjusted depending on an external selection. At this point the INotifyPropertyChange of all the records are fired and a rebind occurs, but only on the currently visible template. This leads to tiles changing colors when zooming in and out as the other views have no been refreshed.
Can anyone tell me if it is possible to implement this in such a way that it would affect all levels of zoom? And is it possible to trigger a rebind without firing the INotifyPropertyChange?
Thanks
After considerable investigation, I came across this issue in the microsoft bug tracker:
http://connect.microsoft.com/VisualStudio/feedback/details/768779/silverlight-forum-issue-with-changing-items-background-color-for-sl5-pivotviewer
The description:
Create a simple data class that implements INotifyPropertyChanged, change all the items' color every 5 secs, but some items have different background color with different zoom levels. This issue was reported from Silverlight forum: http://forums.silverlight.net/p/262082/654612.aspx/1?Re+PivotViewer+SL5+Dynamic+Collection+to+change+item+background+color
So I guess that explains what the problem was. Just waiting for a fix now.
I've got the following problem: in our teams software you can navigate to a site (journal) which loads a individual history (journal entries). The history entries are currently shown in a grid. If you change the SelectedItem, additional data (details of the journal entry) is shown below the grid.
Now my team finds this Silverlight Timeline Control (Silverlight Documentation) pretty good for displaying historical data. I think this either.
My problem is that the only way to put data onto this timeline control is via XML files. That's not a viable solution for our project. Do you see a way to "bind" this to something like ItemsSource? The reason for this is that we have lots of "journals". And every journal you open shows a different history of journal entries. You also can add/edit/delete entries.
You can do this through ResetEvents method. Timeline control calculates event positions, so it needs all events to calculate position of any. It loads them quickly, though, so 10k of events should not be a problem. Please use timeline forum http://timeline.codeplex.com/discussions for more help.
Yes, add propery which calls reset events. This could be observable collection, subscribe to events of this collection and call reset events from there also. Makes sense?
I have a grid control that is trying to display large amounts of data and so it takes a long time to render on the UI thread.
I have added a loading bar that animates and displays depending on if the screen is busy or not (is rendering).
However the loading bar is just freezing when the grid is trying to render. I am assuming this is because there is only one UI thread and that thread it busy.
Does anyone know a way in which I can keep the loading bar animated?
Many thanks,
Matt
You need to process the enumeration or data fetching from UI rendering, do the processing part for get the data ready for UI rendering on separate thread.
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
If you insist on the grid rendering all the data at once, it all depends on whether the grid's rendering code can "yield" or not, kind of like the old Windows Forms "DoEvents()" method. It sounds like it's implemented in such a way that it doesn't, in fact, yield processing back to the UI thread during its rendering, and hence your progress bar never gets updated.
Does the grid ever call into your own code while it's rendering its content? If so, you could use those instances to update the state of the progress bar.
Have you looked into virtualizing the contents of the grid? You can get UI virtualization basically for free if you wrap the FrameworkElements that you need rendered in a VirtualizingStackPanel. If you want somewhat more complexity, you can also get data virtualization by wrapping your dataset with a PagedCollectionView class, and then writing . See here for more details. See also here for another (simpler?) way of implementing the same sort of virtualization.
I'm in the process of teaching myself WPF, and I have run into a small issue that I can't find the answer to.
My test app allows image files to be dropped into a StackPanel. Once an image is dropped, a new user control is added to the stack, and displays some meta-data about the file. All is working correctly, and I can iterate through the child controls to retrieve the values.
What I'd prefer to be able to do is allow the user to persist this data to a file, so they can suspend working on the data. The obvious way for me to do this is to store the data in a DataTable and serialise/deserialise it to xml. However, I don't know how to drive the collection of user controls from a DataTable or DataSet object - in fact, I don't even know if this is the right way to go about it in a WPF app. I am more than willing to admit my ignorance here and take better suggestions if there are any.
Summary of the app logic.
1) File is dropped (from Win explorer) onto a StackPanel
2) File triggers creation of a new user control, which is added to the StackPanel
3) Data is populated in the user control
4) Processing data involves iterating through the control collection.
What I'd like
1) File is dropped (from Win explorer) onto a StackPanel
2) File data is inserted into some persistable object (data table?)
3) updated data table drives the generation of the user control to be added to the displayed collection.
4) save / load functionality persists the data for re-use later.
Thanks in advance
You're on the right track with the second approach, what you need to look at is the ItemsControl - that's a thing which can have items added to it. It's the base for ListBox etc, and you can template it to work as you require. Then there's the DataTemplate which handles which controls are displayed and data binding to those controls when an item is added to the underlying data structure. There are quite a few examples around on the net, try Dr WPF.
In order to make everything work the underlying data structure must support change notification. As everything happens automagically, once the Xaml is setup, you can find yourself in an odd situation. You've added data to a data structure, which in turn has caused controls and data to appear in your ItemsControl. How do you link the data items and their visual controls. The answer is to use some built in static methods ItemFromContainer which links from the graphic to your underlying data item, useful to handle click events, and ContainerFromItem which does the reverse.