In a MasterDetail like page on the detail part it is possible to edit within some TextBoxes. When I select a new item in the master part I have to check validity of all input. Also, when pressing the hardware back button.
My problem is, when I check with CanGoBack I get the answer true, then I call GoBack. Before calling GoBack I'm able to let the page check it's validity and returning false in case it is invalid. Then I do not call GoBack. So far so good. Unfortunately if a TextBox has still the focus from the last input, the LostFocus is only called after GoBack and so the Bindings from that control aren't written back to the model when I check the validity, since it is checked before GoBack.
Is it possible to forbid the GoBack going back somehow?
Determining the control with the focus and call it's BindingManger to update the bindings does not work, since the focus is already on the new selected item of the listview in the master part. And also since I use compiled binding, I have no BindingExpressions I could invoke manually.
Another try was to call Bindings.Update() before the validity check, which is available extra for compiled bindings. But this method works silly. It first writes all the values into the view and then after back to the viewmodel. Thus it overrides my input.
Does someone have an idea how to handle input validation on pages correctly and forbidding GoBack when they are invalid?
Related
I have a customized Grid control that is inherited from Gridview that has search and pagination. Everything works great except this one little thing. Whenever I use the pager to go to the next page, then I use the search, the event that handles the search does not fire on the first click, it takes a second click to get it to fire. Any ideas?
The code for the control is here:
Grid.cs
Important Note
I am aware that it is frowned upon to post large blocks of code... But, the entire control's code is posted to give the whole picture of how it is built. The control itself is a bit on the complex side as it performs searching, sorting, and pagination all server-side; and this code is a completely custom control that just INHERITS the GridView.
I AM NOT looking for someone to write a fix for me, just an idea of why this one situation may be happening!
With that said, to break things down a little more with the code... The search form (text box and buttons) are created dynamically and added in the CreateChildControls method. The search form works perfectly when the Grid is initially loaded, but after using the pagination, the first click of the Search button does not fire the method assigned to the Search button's command event, but the second click does. It seems as though something in the postback is not recognizing the button's command event has been triggered...
A trace of the calls to the methods show:
1st Click - Everything from ViewState is loaded, no postback events are called.
2nd Click - Everything from ViewState is loaded, postback events called.
I'm looking for ideas on where to go from here, as I've been trying everything I can think of page life-cycle wise to see if I can get this functioning properly. The only thing that has worked is setting EnableEventValidation to false on the page that implements the Grid control, and performing the "initial" data bind on every "Page_Load" (not just "if !IsPostback"). But, for obvious reasons, that is not an acceptable solution.
Found the issue... Posting here for anyone who might make a similar mistake.
In CreateChildControls(), I was executing the base before adding the search form to the control. A simple switch around to calling the base after adding the search form, and getting rid of the condition "if (this.HasControls())" resolved it. From what I can see, calling the base after adding any child controls allows those child controls to have their events/handlers properly registered.
I have a lot of textboxes with the TextChanged event. There is also a master textbox at the top, which if I change it and press a "Change All" button, it changes the entire page of textboxes.
Now, the button exists almost entirely on the client side (just uses jquery to change the textboxes), but I want to know if it has been pressed BEFORE my program runs through the 100+ TextChanged events.
I tried adding a server function for it to set a boolean to true, hoping it would fire first, however, the TextChanged events fire first.
TL;DR I need to tell my program in which order to go through the events after a postback.
You really can't change the order of events in the ASP.NET page lifecycle...but you might still be able to accomplish what you're needing. Here's a suggestion...take it FWIW...
On the client side, you could add a Javascript event handler (or amend one that already exists) to populate a server-side form field with a magic value (doesn't really matter what). On the postback, inside the Page_Load (and/or in the TextChanged event handlers), check for the presence of the value when IsPostback = true. You might have to wire up (a bunch) of different handlers to make the same check, so this may be too cumbersome, but its at least the seed of an idea, perhaps.
Won't promise its very elegant, but it should at least get you closer to what you need.
Even if I associate the button with a class derived from ICommand, I am still left with figuring out how the button should trigger the CanExecute method and refresh its enabled state. I do know about the CanExecuteChanged event for which a button with an associated command registers, but see the following paragraph for why this is troublesome.
On a plain old dialog consisting of some 10-15 controls, it seems haphazard to have to process every change notification for every single one of those controls, triggering the CanExecuteChanged event on the button's command, causing the button's enabled state to be affected by the CanExecute method's return value. Even stating what needs to be done in the last sentence was quite cumbersome.
There must be a better way of coding a WPF dialog, so that the confirmation button (e.g., OK) is grayed out until all controls have valid information and is enabled at that point in time (i.e., when all controls are properly filled in). Sample code, ideas and pointers to articles would be immensely appreciated.
Thanks
I don't see anything haphazard here. Since your condition is "all controls have valid information", this can occur after any control is edited, and therefore you need to listen to change notifications from all controls.
On a plain old dialog consisting of some 10-15 controls, it seems
haphazard to have to process every change notification for every
single one of those controls,
I don't think so. Every Textbox, checkbox changed event is handled by the same handler, say SetState(), which calculates the overall state of the dialog. Every time a control is edited, the entire state is recalculated.
until all controls have valid information
Then that object would have a boolean property EnableOKButton, let's say, which is set according to the updated state. Then that property is bound to the button's Enabled property so it automagically changes - without dealing with extraneous events.
This seems very simple, but I can find nothing on a web concerning the behaviour I want to add to my custom control.
My custom control is a textBox with a list of choices. When the text entered by the user is not part of the list, a popup will appear with the list allowing the user to select a correct choice.
Sometimes, there may be a default button on the container in wich the custom control has been added. If so, when the enter key has been pressed, if the text is wrong, The popup must been displayed. If there is no default button, on enter, nothing must happen even if the text is wrong.
To be able to create this behaviour, I must be able to detect the presence of a defaultbutton in the container, and it must be done inside the c# code of the cutom control.
I hope the description is clear enough.
Thanks in advance
Have you thought about implementing an MVVM approach and the Command pattern? So long as your view model knows what the choices are, you can bind the default button to a command. So long as the commands CanExecute handler returns false, i.e., an appropriate choice has not been entered/selected, the button will be disabled and won't respond to the user pressing enter.
Since I was unable to know what other controls I had from the custom control I chose to go like this:
I made a recursive function to find the first parent using FrameworkElement.Parent
Having the parent, I could take a look at every controls it contains.
As soon as I saw a button, I had to verify if IsDefault.
For this one, I used the VisualTreeHelper GetChildrenCount(DependencyObject obj_Parent) and GetChild(DependencyObject obj_Parent, int childIndex). Recursivity once again...
It works very well even though it means more code to execute.
I have a textbox in one grid-view column where upon entering a particular value and losing focus of the textbox, should post to the server to get the text validated through a server-side method. If the entry is valid, a result set to fill rest of row cells would be returned, else the bgcolor of the textbox needs to be changed to Red.
I tried posting back through the obvious way, i.e. making the textbox's autopostback as true and wiring up a server-side OnTextChanged event handler to validate the entered value.
It is working with this setup, but is also affecting the remaining page controls behaviour. For example, if I click a button in some other grid after entering some text in the textbox, the OnTextChanged handler gets called thus preventing the button's click event, which I also wish to call to execute its functionality.
Kindly suggest what alternatives/corrections I should carry out to enable textbox content server-side validation plus making the other controls/updatepanels work as expected.
Me dumb. I tried everything from creating PageMethods, UpdatePanels to jQuery as hinted in lincolnk's reply. But the thing which finally worked was removing the Autopostback attribute from the textbox control.
After removing it the OnTextChanged event executed each time any server postback was initiated after changing the text. Thereby, executing both the OnTextChanged method and the other control's method. :)
I can think of a couple general approaches.
Create a web service with your validation routine and manually make the call (jQuery or whatever) when the text changes. Manually update the client display when you get a result.
Convert your gridview column to a templated field. Add a CustomValidator and wrap the textbox and validator in an UpdatePanel. Set the textbox to auto-postback and the UpdatePanel to conditional update so only the one you are using is refreshed.
Option 1 is kind of an end-around the typical asp.net process, and you would still want to validate everything on the server-side when the page is posted back.
Option 2 might have performance issues, since you're hitting the page again every time you do a validation.