I've got an ASP.NET 4.0 site. In the site there's a treeview control inside an UpdatePanel.
Keep in mind - when the user first visits the page, no postback has occurred (more on this in a minute).
When the user clicks on nodes in the tree, it triggers a postback. I can set history points as the user is moving through the tree - that's not a big deal. The history point is the ID of the selected node. (I want to use this to drive other information on the page)
There are two behaviors I'm seeing, and I'm stumped as to how to rectify these:
First, the history points always seem to point to the current item. If I start on Item A, then click Item B, when I hit the back button, I wind up at Item B for a couple of clicks (as if the history points are all set to the same value). I thought the history should be a running list of the nodes the user clicked...but in this case, it seems like the list is always a collection of history points with the current ID. (If anyone knows how to expose the collection of history points in the scriptmanager, I'd love to hear how)
Second, and more of a headache, is that when the tree initially loads, there's no postback. Is there a way to set a history point without an Ajax postback? (I'd like to have a way to preserve the default state for the tree, but right now going to item A from the root, then clicking back takes the user to whatever page they were on before the hit my page)
Has anyone else noticed weird behavior with the ScriptManager's history points?
I've also thought about alternatives - like viewstate, hidden fields, cookies, session variables...but I haven't had any luck with any of the solutions I've tried. Is there a way to get the back button to work without the history points? (I don't think there is)
To set a history point without a postback, you call ScriptManager.AddHistoryPoint().
I would venture a guess that adding your history points is not the problem, but in the ScriptManager.Navigate, you are not correctly loading the state back, or maybe you are relying on session information that has already been updated to Item B.
One way to see what is in the history state is to give each history entry a name/title that is descriptive enough to identify the state of the page. For testing, you could use a shortened version of the state string hash or just build a string to identify the state of the page and then when you click and hold the back button to view recent browser history, you will see the pages with descriptive names to identify them.
Here's the MSDN page talking about that: http://msdn.microsoft.com/en-us/library/cc472966.aspx
BTW: Sorry I'm late getting to this question. If you are still having problems, post some code so we can see what you're doing. I have implemented the history point functionality on pages with the tree control in an update panel on several of my pages.
Related
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.
Shopping Cart items are grouped and shown as links. For instance, a user has got a group of "T-shirts". When he clicks that link ("T-shirts") a bootstrap modal window pops up with all the t-shirts listed as links on the right and all the details (picture, size, price, etc) about the selected (first on the list) t-shirt are shown on the left.
Now, when a user clicks on any other link (inside that modal window) to see the details of a different t-shirt a request to the database is made. Average user can make over 100 request in a matter of minutes, checking his stuff and retrieving the same data over and over, which looks as a waste of resources to me.
My question is - how do I go about optimizing this process?
Can I load all the data about the chosen group and just pass it to the modal window every time user clicks on a different item?
If so, where do I store this data?
As far as I understand session variables still require some server side work which I would like to avoid.
Are cookies a way to go in this scenario? Or is it an overkill and I shouldn't be bothered at all?
Thanks
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.
I have an ASP.NET page where at the top of the page is a search box. There are 2 text boxes - one is an autocomplete extender for the Name on a database, and one is just inputting the ID.
The page features DetailsViews and GridViews primarily, and even when no account has been searched for, these display blank data which is not ideal. I sort of fixed this by using if (IsPostBack), encasing the elements in a placeholder and setting it to visible only if the page ispostback. But this doesn't cover if the user types in an incorrect ID.
Also, some accounts have huge amounts of data inside the GridView's. I had an issue where because I have no way of detecting when a data source's rows has changed, I end up binding whenever the page loads (Page_Load method). I've come to realise this is simply very bad - there are lots of times when the user can click various things in the page and have the page postback, and it takes an eternity to load each time I click something for accounts with lots of data.
Anyway, my question is essentially two-fold but I have a feeling the solution will be similar:
1: How can I detect when there are no accounts returned when searching, and disable the Grids/Detailsviews and show an error message?
2: How can I figure out when the user searches for another account and only rebind the grids after that has happened?
Thanks
This method is very ugly but it'll get the work done.
1) To Check whether there are no records; after the AutoComplete Extenders Webservice is called if no record is returned put some value in Session like
Session["NoData"]=true;
if Records are found then;
Session["NoData"]=false;
after the webservice is called do ajax request to check that session & on the basis of value do what you want.
2) You can achieve this also by following the above option.
I'm trying to persist the contents of a textbox through a postback, and I've exhausted all of my effort but can't get it working right.
What should happen is:
User selects a radiobutton
Depending which button was
selection, a usercontrol is loaded
to specify some data and a viewstate
to say which enum type it's
equivalent to.
When they click
save, if the UserControl is just a
textbox input - the simplest), the
contents are read and saved, then
saved to the database with the
format(the radiobutton choice) so
they can be deserialized again
later.
The page posts back, and
the value and format are read from
the database, then the right control
is loaded.
The problem is - the first time the page posts back, it works. Every other postback it resets to the default value of the textbox.
I have a very similar setup elsewhere, so I'm thinking it might be a minor thing I'd never think of. There's a lot of code, so it might be easier to talk about what to do (load the dynamic control, populate the values etc) rather than how to do it.
There was actually a bug in my original code which meant it would never have in the way I was using the modified version. Apparently state is restored in Page_Load, so any controls need to be initialized by to have their values restored.
Creating the control in Page_PreLoad, then populating it after Page_Load solved the problem.