Does anyone have any pointers / examples on how to resolve many issues that are possible in multi-user scenarios when using data-virtualization. Lets say that we are talking about WPF and DataGrid. Implementing a virtualized collection which loads on demand is not too difficult. However, without a staging area where temporary results of the original query are stored, we get into concurrency issues like:
Loading new page could fetch incorrect data (concurrent user adds and removes some records, leading to same total count of records, but which results in page fetching duplicate entries that are already displayed somewhere above in the grid)
Preserving user-selection in the grid when scrolling and loading new pages, in which there could be a possibility that once selected items have expired from cache, and once reloaded, we find out that someone deleted them. We can deselect everything and show the message to the user, but :/ Also, if selecting with Shift-click (multiselect) somewhere close to the end of the list, what should be done when some items "appear" in the middle of list upon loading some of the middle pages (concurrent user added items).
It is useful to keep in mind that nothing on the screen of your user is technically up to date. The moment you show it you are lagging on the master dataset.
1) Yes, of course. But you can always keep track of the first record you are showing on your grid and get your next page sized set from there. Those which are deleted will drop out of view, of course. Optionally, you might try and use a library such as ZeroMQ or RabbitMQ and broadcast dataset changes and update your datagrid live if they are currently shown. It still won't be perfectly in sync, obviously but you will reduce the window in which they won't be in sync.
2) When you have selected items you keep track of their primary keys. I don't know what you want to do with those which are already deleted from the master set. But you can always act on all the others, right? Even if they aren't shown anymore you can track the PK's. And reselect them when loading a page.
Related
I have a rather simple sounding requirement. Currently, we have a Combobox which is rather inefficient because it attempts to load all the data from DB when the box is clicked. This Combobox is not typable and all I have to basically do is ensure that the data is loaded in chunks at the appropriate times i.e. when the user is at or near the end of the Combobox.
My initial thought was that there should be an event which I could bind to when the user scrolls towards the end of the Combobox, but no such event exists based on what I could see in event list.
My alternative solution is to bind on mouse wheel down event and have a method which constantly polls whether the last item is visible (although I'm not sure such property exists) and if it is, load more data.
My last hunch is that there should be some sort of asynchronous stream data approach to this problem which would just basically load rows without locking up the UI continuous instead of one big chunk.
Can anyone suggest anything and maybe show a quick demonstration?
Kind regards,
Vocal.
I'm pretty new to WPF (and in a professional setting, C#), and have been presented a challenge to identify and fix a possible memory leak in one of our apps.
The app integrates with Shopify, in order to be able to use the webapp inside the WPF app (integrates payment systems, shopify orders, product listing, etc.).
The custom control I am refactoring, originally had some "scrollview" (for the categories/products to be displayed and navigated around), with 9 elements being displayed at each time. The problem with it, was that with each scroll down (and loading of +9 products) they would stay loaded in memory, eventually blowing up the app (not exactly blowing up, but filling memory until the host runs out of it, slowing the app down to a crawl).
After talking to my senior and brainstorming possible solutions, we came to the conclusion that the best option in both "simplicity" and user-experience, would be to paginate the content.
So in order to accomplish that, we have the "old view" (has methods to populate a child user control - each "product", getting updated product info from shopify's api, and it also has the navigation events/logic) and I have created a new user control, responsible for "containing" the other user control (this is in essence a page of products or container), where I keep track of current product IDs (to execute shopify API query each time we navigate - essentially loading 9 products every time the user navigates back and forward) and the current "page" the user is browsing.
I am trying to retrieve 2*9 products (if the chosen category/brand of product has more than 9 items - the "2 page loading method" runs, if not we default to try and load 9+1 products), on the first "pass/iteration", in order to "fool" the user and not having them wait for the query result to come (every time we query, we download product info and images, etc.). Essentially loading 1 page ahead every time (and keeping track of the current page index, previous page index and next page index - for each of these indexes there is a productID that matches them at any given time - they are queried to the API each time we need to retrieve them). Example: page0 - id:123; page1 - id:321; page2 - id:456. click next -> page0 - id:321; page1 - id:456; page2 - id:232. edit: The page/id that was discarded/ isn't in view anymore, gets disposed via Dispose().
I am retrieving the product IDs I need to keep track of fine - I haven't, yet, implemented the current page logic, but I am pretty sure I will have to make this UC communicate with the old UC - to send and retrieve current page index - but as I am pretty new to WPF - I don't understand how I go about wiring up/firing button events from the other UC in this "container" thing or how to access them (I have tried the namespace "way" to try and call the old user control, but I can't call it in code-behind (thus not being able to access the buttons via dot syntax).
There probably is an example of this somewhere online that I could refactor and base my code on, but I am currently not able to find it without any help from someone more knowledgeable.
Thanks in advance.
In my WPF application, I've got a screen with a tab control. Five of these tabs contain datagrids which need to display a large number of rows (at least 5000). The tables are bound to ObservableCollections of Part objects. Each row displays around 20 points of part data. My problem is that, after the user enters the information they require and generate the data, clicking on a tab causes the application to hang for 30-60 seconds. After this the datagrid finally loads, and with the right virtualization settings, they perform at an acceptable rate (not exactly fast, but not too slow). If I disable virtualization, the program uses up way too much memory, and the loading time isn't really affected.
The most offensive tables consist of about half a dozen template columns. Each template contains controls inside a stackpanel or a grid; basically each row is split into two, like a double-row. This layout is a requirement, and paging is probably not something that the customer is willing to accept.
This is the most important screen in my application and I'm pretty much at a loss about making this work. Is there anything I can do to speed up this process? Perhaps ObservableCollection is the wrong choice?
Can you please provide more insights...
Can you check how much time is spent in "generating" the 5 collections of 5000 rows each? (this is what I assume you are saying)
With virtulaization "on" what is the UI loading time "after" we assign the collection to the items source?
What happen if you bind "ItemsSource" to the respective datagrid only when the tabItem is actually Visible \ Selected?
Do you datagrids have default sort member path? Grouping? Filter Paths?
These are a few things I would target to start on the issue.
Well it's not playing actually.
I have a database with about 200 list of items in it. I've used DataTable to fetch all the data in single connection.
Then created a windows button that creates new button for all the items.
It is OK and I was able to do it easily.
But I stuck over two things..
First is, I have limited space in my windows form, that's why I want to load only 30 buttons at first and then upon second click event, I want to load buttons for remaining 30 items and so on..
Second problem is, even if i managed to solve the first problem? How to arrange them in proper row/column?
Please help.
Grab an ordered list of records, split it to a list of "pages" (which is also a list of records) and use navigation buttons to change the context of current page.
Why don't you take a DataGridView with a BindingSource and a DataGridViewButtonColumn? With this as a starting point you can simply glue them together by calling:
myDataGridView.DataSource = myBindingSource;
myBindingSource.DataSource = myDataTable;
Update
Surely you can try to do the whole visualization on yourself by using a TableLayoutControl. But the DataGridView is a control that is specialized to visualize data in a data grid (hence the name of it).
The grid view is a very complex control, but it has a lot of nice features which make your results looking more professional by simply configuring some properties of it. For example simply set the property AutoSizeColumnsMode to Fill to simply avoid horizontal scroll bars and set the Column.AutoSizeMode of some columns to e.g. DisplayedCells to enforce which columns should be wrapped, etc.
Also there are a lot of features regarding to data validation, formatting, etc. So i think even if the step-in hurdle is a little higher you got a much better visualization then trying to do all this stuff manually by taking a TableLayoutPanel. Last but not least there are lots of examples about how to use the specific properties within the MSDN and if you get really stuck just search for the problem here on SO or on the web and if you don't find a proper solution just ask a question here on SO.
Need help with technical-designing of a website.
I have a main page with a multi-paged grid.
Whenever you press on a row, you navigate to an extended details page about this row.
Here comes my question, I want to be able inside the details page to add "Next" and "Prev" buttons according to the original grid. (Mind you, the grid can be filtered and ordered in various ways).
How would you approach this scenario?
Update:
We can not work with Session variables since there are scenarios where user moves from a grid, to a details page and then to another grid, and so on...
So saving last dataSet in a session varible will be useless.
You need to create some state to manage your UI workflow. When you display the grid, it is bound to some collection of data. That collection is likely sorted and filtered. Since you will need to reference that data set as part of a larger workflow, you need to either keep the whole (sorted and filtered) collection around (if it is small enough), or keep the criteria that will let you re-query for it (if it is large) in your users session. When you select a row and redirect to the detail page, pass in the selected record in the query string.
Combining the current record from the query string, and the data or criteria stored in the session, you should be able to retrieve the "next" or "previous" record in tandem with what the original data grid displayed. If the user selects Next or Previous, the only requirement would be redirecting to the same page with a different value in the query string for the current record. Since the rest of the criteria or data is in the session, paging through detail pages should be trivial.