I am in the process of evaluating the ASP.NET Wizard Control. Where we need to collect data from different steps, validate data and towards the end I should be able to show a data summary.
I would like to know from the group if anyone has used this control and what issues they faced. Are there any usage limitations with this control?
The Wizard control can save you a lot of plumbing time if you use it well - however, learning to use it well may cost you more than the plumbing time that you save. If you plan to reuse it, then the initial investment in learning about its idiosyncracies may be worth it.
I have built a wizard in which the steps displayed in the side bar depend on which step you are at (and on what you have done to that point). It follows that the step you go to when you press Next or Previous is also determined dynamically.
To implement this, I read a lot of stuff about dynamically disabling steps, hiding steps, and adding and deleting steps. The latter led me into deep water with the ViewState. For what it is worth, here is my basic approach:
You can control which steps are visible in the sidebar by setting the step ID (and Title if set) to an empty string e.g. I have the step names in arrWizardSteps() and my steps defined as integer constants, then use
For i = intCREDENTIALS To intADDITIONAL_INFORMATION
Wizard1.WizardSteps(i).ID = IIf(Wizard1.ActiveStepIndex < i, "", arrWizardSteps(i))
Next
If the steps are relatively independent, you can handle the SideBarButtonClick, PreviousButtonClick and NextButtonClick events by calling the same routine, which you construct to handle leaving the current step, and entering the next, irrespective of which button you clicked to make the transition. For example, the routine might store the data captured by the controls of the current step, and load some data into the controls of the next step.
If you do handle these events, you probably need to handle changing the ActiveStepIndex yourself. The wizard will increment/decrement the ActiveStepIndex (depending on which button was pressed) if you don't change it (unless you set e.Cancel=true in your handler where e is the WizardNavigationEventArgs argument to the handler).
If your code for hiding steps needs to know the destination step then you need to put that code in PreRender, since at that point the wizard will have moved to the next step and you will know what it is.
Personally I don't like the wizard control. Its quite rigid and I didn't find it very nice to work with. Since then I have used the MultiView control inside and UpdatePanel with User controls in each View for each step for my wizards. This way it can be completely flexible.
With the MultiView approach you can also see all steps of the wizard easily in the designer.
This is just my option on the control though, I didnt give it much of a chance on its first visit.
Related
I have a custom UITableViewCell, and when the user clicks a button i make a request to a server and update the cell. I do this with a NSUrlConnection and it all works fine (this is all done inside the cell class) and once it returns it fires a delegate method and the tableivew controller handles this. However when i create the cell in the tableview, i use the dequeue method and reuse my cells. So if a cell has fired a asynchronous nsurlconnection, and the cell gets reused whilst this is still going on, will this in turn erase the current connection? I just want to make sure that if the cell is reused, the actual memory that was assigned to the cell is still there so the connection can fulfil its duty??
You can customize the behavior of a UITableViewCell by subclassing it and overriding the -perpareForReuse method. In this case, I would recommend destroying the connection when the cell is dequeued. If the connection should still keep going, you’ll need to remove the reference to it (set it to nil) and handle its delegate methods elsewhere.
It's never a good idea to keep a reference of a connection or any data that you want to display in a cell, no matter how much of effort you put into it afterward to work around to arising problems. Your approach will never work reliable.
In your case, if the user quickly scrolls the table view up and down, your app will start and possibly cancel dozens of connections and yet never finishes to load something. That will be an awful user experience, and may crash the app.
Better you design your app with MVC in mind: the cell is just a means to display your model data, nothing else. It's the View in this architectural design.
For that purpose the Table View Delegate needs to retrieve the Model's properties which shall to be displayed for a certain row and setup the cell. The model encapsulates the network connection. The Controller will take the role to manage and update change notification and process user inputs.
A couple of Apple samples provide much more details about this topic, and there is a nice introduction about MVC, please go figure! ;)
http://developer.apple.com/library/ios/#documentation/general/conceptual/devpedia-cocoacore/MVC.html
The "Your Second iOS App: Storyboards" also has a step by step explanation to create "Data Controller Classes". Quite useful!
Now, when using NSURLConnection which updates your model, it might become a bit more complex. You are dealing with "lazy initializing models". That is, they may provide some "placeholder" data when the controller accesses the property instead of the "real" data when is not yet available. The model however, starts a network request to load it. When it is eventually loaded, the model must somehow notify the Table View Controller. The tricky part here is to not mess with synchronization issues between model and table view. The model's properties must be updated on the main thread, and while this happens, it must be guaranteed that the table view will not access the model's properties. There are a few samples which demonstrate a few techniques to accomplish this.
I'm populating a GridView with code, setting datasource to the dataset returned by a query. So apparently sorting and paging don't just work magically like if I use a datasourceid= some sqldatasource.
I've found a number of examples of how to do this on the web, but they all appear to re-execute the query every time. Shouldn't the contents of the query be saved in the view state? Is there some way to just get the previous query results and re-sort without having to go back to the database? (Is it saving all the data in the view state? If so, why can't I get to it? It seems pretty dumb to send it all to the user's browser and send it all back, wasting all the bandwidth, if there's no way to get to it.)
Also, if I try to allow paging, it appears I again have to re-execute the query every time the user goes to another page. And if the user sorts and then pages, then I have to remember what the sort order was in a hidden field or some such, so I can re-read the data, re-sort, and then go to the right page.
Given that when you use a data source control all this behavior is built in, I think I'm missing something here. But given all the examples out there that do it this slow, hard way, if I'm missing something, a lot of other programmers are missing it, too.
If you're using an ASP.NET GridView control every time you sort a column or page through the data set then you're making a server postback. Sorting and paging with this particular control has never worked 'magically' and has long been a bugbear of mine.
You can speed things up by storing the data source that you're building the grid from in memory, either as a session or through the ViewState. Both have pros and cons and I suggest you read up.
If at all possible I suggest forgetting the ASP.NET GridView and looking at a client side solution such as the jQuery jqGrid. It uses AJAX calls to sort and page and is much, much faster and less of a headache. The only drawback is the learning curve but believe me it's worth it in the long run.
Yes the gridview re-execute the query every time.
If the query takes too long, you can manually store data in the session, or ViewState. And in the Algorithm that populates the grid just read them directly for it, instead of running the query.
you can, in the page load event, run the query one time when there is no postback (you can check for postback with
if (!Page.IsPostBack){
//Run the query and save it to the session
}
and the the method that populate the grid, should read from the session directly. no need to run the query again
Afternoon all,
I'm currently profiling a rather large C# WPF app, trying to eliminate a few performance issues. One involves a 5-8 second stall that occurs when switching to a particular (rather large) UserControl. I've narrowed this down to a RadGridView contained in this UserControl that's taking a long time to load and update itself, stalling the UI thread and making the entire application unresponsive. Obviously, we'd like to eliminate this stall if possible.
I have tried stripping away any custom styles and DataTriggers on the grid, but while this acted to reduce load on the UI thread in general, the stall still remained, seemingly undiminished. Through ANTS Profiler, it seems that the measuring and layout of the grid is mostly to blame, along with some loading of XAML templates. With no grid rows, the UserControls loads significantly faster, and it seems that adding just a small number of rows is enough to bring about this stall. The grid has virtualization enabled for rows and columns, but this doesn't seem to help. The call graph is tremendously deep when examined, and it seems to be calls that raise update notifications, update layout, load XAML and, above all, measure child FrameworkElements that are to blame.
For a couple of potential solutions, I'm thinking about keeping the UserControl in memory but hidden to reduce the costs of switching to it, or populating the grid, perhaps incrementally, well after the UserControl has loaded. There might be a lot of work with the former, as the control subscribes to a number of things, which would need to be connected to, disconnected from and reconnected to as appropriate. The latter might also involve a fair bit of work, but might be a better solution, because then at least we could try to mitigate the stalling ourselves, or at least warn the user when it was occurring.
If the problem persists, we're likely to ask Telerik to have a look at it, but I thought I'd ask here first in case anyone has encoutered such an issue before (not necessarily with RadGridView, even) and found a solution of some description.
Cheers.
The problem is you need a collection that implements ICollectionChanged properly.
Try this after adding all records to your source collection (one which should NOT raise any CollectionChanged events after each add), it works:
public void AddRange(List<TValue> values, int startingIndex)
{
// add all the items to your internal list, but avoid raising events.
// now raise CollectionChanged with an IList type.
CollectionChanged?.Invoke(collection, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, addedValues, startingIndex));
}
Notice we're passing IList<TValue>, NOT TValue. When it sees a list, it adds them ALL before processing. The startingValue is usually the .Count of the list before you started adding items.
Steps:
Subclass a collection type that doesn't already implement INotifyCollectionChanged. Plenty of open source examples are out there.
Add the method above and use it after you've added your items.
My RadGridView is binding against a QueryableCollectionView which uses this list as its SourceCollection. I don't know if you can bind against this list directly.
One strange behavior with RadGridView is that if you add say, a million records this way, it WILL be quick, but all the new rows will be blank, and you can watch RadGridView slowly populate them with data from the topmost new item down. My solution to this is to bind against QueryableCollection and set its PageSize sufficiently small so the users don't see this.
I'm stepping through my code to figure out why a certain function takes more time to run the first time it gets called than on successive calls. The code flow for each function call is the same up to when a dispatchEvent gets called. I'm pretty sure it's different afterwards, as that call takes a lot more time the first time around. Unfortunately, I have no idea which other parts of the code chew on this specific event and thus cannot step through the handling of such event.
The question: is there a way to either figure out who handles such events or magically step through the handling code without explicitly setting breakpoints there?
thank you!
Not in an easy fashion, no. It's a pro and con of Flash (or any event based framework). You don't know when it's fired, where it's fired from (think bubbling), or who is listening for it. But at the same time, anyone could listen for any event, from anywhere (so long as it's within the display tree).
Normally what I do is just do a workspace search (ctrl+H in Flash Builder) and search for that specific event (you should be using static constants for dispatching/listening event types) and see who's doing what.
What I'm trying to do is have a 3 state tree expansion.
I have three different icons for "expand" "collapse" "semi-expanded" which I want to use to show a partially populated tree control with all nodes initialized to semi-expanded state and then on clicking the "semi-expanded" icon it gets data from server and populates the tree and open that branch with "expanded" icon.
I tried looking for it but couldn't find anything close to it except the 3-state checkbox but don't know how to use it on 3 state icon when tree would only maintain 2 states.
Thanks in advance.
I think what you are looking for is called a lazy-loading tree. There are lots of examples your can google for, but here is a great example.
As far as the visual part of your request goes (3 different icons to show that state of the branch or node) - you could easily handle that with a custom renderer, by looking at a flag on the node for it's load status.
Does that help?
A 3-State tree control is a bit uncommon and might therefore be a bit confusing; consider that even simple 3-state checkboxes are relatively rare and users may not be accustomed to them. Maybe that's why you didn't find such a tree control.
Thus, maybe you should consider using an alternate design that doesn't require 3-state controls.
For example, the node could start in collapsed node. If the user expands it, and there is no data yet, show a single sub node with the text "retrieving data..." (and a progress wheel or other progress indicator, if you can) and start data retrieval. When the data arrives, replace this sub node with the actual data.