I just switched to using the CSS Adapters for my TreeView control on one my ASPX pages. Now, for some reason, I cannot use the SelectedNode method except in my OnClick() event. ALL other events show that the SelectedNode is NULL. I am currently using a bunch of non-visible labels to store tree info everytime someone clicks on a node. Very, very, very wrong way to use this control. What is the secret to getting the control in code behind when CSS Adapters are enabled?
The adapter for the TreeView control does have some viewstate handling but you are right the selected node property is null on postback.
If you hover over the root node the status bar on the browser will show something like:
javascript:__doPostBack('controlid', 'eventargument');
//or
javascript:__doPostBack('tv', 'srootnodevalue\\childnodevalue');
You can catch the event argument in the code behind which describes the node you are accessing and its value as a string like 'node\value'.
if (Request.Form["__EVENTTARGET"] != null && Request.Form["__EVENTARGUMENT"] != null)
{
if (Request.Form["__EVENTTARGET"].Equals("tv")) //tv is my treeview control id, and the first parameter in __doPostBack()
Tv_SelectedNodeChanged(Request.Form["__EVENTARGUMENT"]);
}
protected void Tv_SelectedNodeChanged(string argument)
{
//process the argument string 'srootnodevalue\childnodevalue'
}
The treeview viewstate seems aware of the selected node by the adapter's representation of it as class="AspNet-TreeView-Leaf AspNet-TreeView-Selected" when it renders.
Still, there may be a nicer way of doing this...
Related
I created a class CustomCombo.as that extends ComboBox. What is happening is that the CustomCombo combobox is showing as being editable. I do not want this and I cant find the properties to set the editable to false.
I also tried setting the combobox's textInput.editable control to false, but to no avail.
Any help would be greatly appreciated.
CustomCombo.as
package custom {
import spark.components.ComboBox;
public class CustomCombo extends ComboBox {
public function CustomCombo() {
super();
// this.editable = false; //<-- THIS DOESNT WORK ***Access of possibly undefined property editable through a reference with static type custom:CustomCombo
// this.textInput.editable = false; //<-- THIS DOESNT WORK ***Cannot access a property or method of a null object reference
}
}
}
After rummaging through the Flex 4 API I found that they suggest to use the DropDownList control. From what I can see is that they removed the editable property from the ComboBox control in Flex 4, but I may be wrong.
I implemented DropDownList and that solved my problem.
I see that you're using spark and not mx. The editable property I referred to is applicable only to mx based list. In spark, ComboBox extends DropDownListBase and is editable by default.
The ComboBox control is a child class of the DropDownListBase control. Like the DropDownListBase control, when the user selects an item from the drop-down list in the ComboBox control, the data item appears in the prompt area of the control.
One difference between the controls is that the prompt area of the ComboBox control is implemented by using the TextInput control, instead of the Label control for the DropDownList control. Therefore, a user can edit the prompt area of the control to enter a value that is not one of the predefined options.
For example, the DropDownList control only lets the user select from a list of predefined items in the control. The ComboBox control lets the user either select a predefined item, or enter a new item into the prompt area. Your application can recognize that a new item has been entered and, optionally, add it to the list of items in the control.
The ComboBox control also searches the item list as the user enters characters into the prompt area. As the user enters characters, the drop-down area of the control opens. It then and scrolls to and highlights the closest match in the item list.
So ideally, you should be using DropDownList in this case.
You're getting null error when trying to access textInput from the constructor because it hasn't been created yet. In mx based controls (Flex-3), you can access it from the creationComplete handler; I'm not quite sure how to do it for spark based controls.
Update: I think I've figured out how to access skin parts in spark (though you might wanna use the DropDownBox instead). You have to override the partAdded method.
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == textInput)
{
textInput.editable = false;
}
}
There's one catch though: it may not work in this case. The source code of ComboBox.as says that
the API ignores the visual editable and selectable properties
So DropDownList it is!
Initial answer, posted for mx ComboBox.
This shouldn't happen as the default value of the editable property is false.
Try explicitly setting the value to false from the constructor.
public function CustomCombo() {
super();
this.editable = false;
}
What is the trick to get the controls inside the FormView. I was getting them with FindControl() but, now i cant get access on them. Example: i have some ImageButton on the FooterTemplate, great i can get those smoothly, when it comes to the controls inside the FormView!!! null every control. Do you think i should name them differently in every template?
This gets me thinking about the table causing this noise!
I'm using the DataBound Event and checking for specific Mode! Any ideas? Thank you.
[UPDATED]
This is working
if (this.kataSistimataFormView.CurrentMode == FormViewMode.Edit)
{
ImageButton update = (ImageButton)this.kataSistimataFormView.FindControl("btnUpdate");
update.Visible = true;
But this for some reason no
CheckBox chkBoxPaidoi = kataSistimataFormView.FindControl("chkBoxPaidoi") as CheckBox;
FindControl is not recursive. What I mean is that it will only find controls that are within the child controls of the control you are searching - it will not search any child controls of the child controls
If you have placed the control you previously were looking for within another control then you will have to either search within that new control or, if you still want to use kataSistimataFormView as the parent control, you may have to use a recursive search.
Google for "findcontrol recursive" there are some good examples that you can probably just cut-and-paste.
As it seems this was caused because of the same naming ID's on various templates, Insert,Edit,Item. Even this is supported by the compiler, has problem when you are going for them programmaticaly later.
Thank you all.
Did you ever get this figured out? If you know the ID you can use this recursive function:
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
Found here:
http://www.codinghorror.com/blog/2005/06/recursive-pagefindcontrol.html
I have a ASP.NET treeview populated with custom treenodes (ExtensionRangeTreeNode subclassed from TreeNode).
On postback the treeview is populated with TreeNodes, not my custom treenode class.
What's up with this?
Thanks,
BP
This forum entry may answer the question :
Basically, it is said a custom treeview control has to be used. CreateNode function must be overriden to instanciate the right TreeNode type. Here, it would be ExtensionRangeTreeNode instead of "CustomTreeNode".
public class CustomTreeView : TreeView
{
protected override TreeNode CreateNode()
{
return new CustomTreeNode(this, false);
}
}
Of course, you will have to add the ExtensionRangeTreeNode(Treeview treeview, bool isRoot) constructor signature to your current ExtensionRangeTreeNode implementation.
Without looking at your particular code, I can only assume that you custom TreeNode is not using ViewState. This would explain why it is not getting populated on postback.
DoesExtensionRangeTreeNode fully handle saving itself to the viewstate fully? If so, can you cast the returned nodes to that type?
Is there a client event that I can use for when a DropDownList's data has been loaded/bound onto the control? I need to trigger event on their side when this happens.
Basically, I am trying to lock out the controls while the data is being loaded as if there is a slowdown (not uncommon) a user can start inputting data and then lose focus as they are typing.
I tried doing this in the tags but the methods located there seem to stop working after the first postback! (Any help there would be greatly appreciated). As a workaround I tried attaching the events to the elements themselves and while this works for locking, using the onchange event, I am unable to unlock it upon the data successfully loading!
Any ideas? Thanks for the answers so far :)
Since data will be bound on the server side, you don't have a client-side event for that specific event, however, one the page has rendered, the data will be there, so you may want to run your client script in the document.load event, or using something like jQuery's document.ready event. That will trigger your script to run once the page (including your bound drop down) is finished loading.
Jason is correct here in that you cannot "notify" the client when such an event occurs. One thing you could do, is call the Page.RegisterStartupScript() method to do something with JavaScript once the page has finished loading (and assumedly that the post back that has done your databinding has occurred). Again, this assumes that you want to do something on the client side once the data binding is complete, as opposed to server side.
Are you able to use ASP.NET AJAX in your application? If so, you can have the selected event open up a modal dialog in which you can display your "processing" text while you are populating the drop down list. That way the user does not have access to any other controls and you can do what you need without worry.
i use the following code in my master pages for my websites. This stops the user from attempting to use a control before its completely bound. I have found that if a control hasn't been completely bound (slow connections) then the page blows up.
Essentially the script hijacks the post back if that page isn't done. Allowing the user to not do anything until the page has finished processing. I wrote this a year ago and its come in very handy.
first set the onload body tag to setdopostback()
add this in a scrip block in the body.
var boolDoPostBack = false;
if (__doPostBack)
{
// save a reference to the original __doPostBack
var __oldDoPostBack = __doPostBack;
//replace __doPostBack with another function
__doPostBack = AlwaysFireBeforeFormSubmit;
}
function setdopostback()
{
boolDoPostBack = true;
}
function AlwaysFireBeforeFormSubmit (eventTarget, eventArgument)
{
var x= document.readyState
if (x != "complete")
{
if (x == "loading" || x == "interactive" || x == "unitialized" || x == "loaded")
{
//do nothing with IE postback
}
else if (!boolDoPostBack)
{
//do nothing with FireFox postback
}
else
{
//alert('Allow Postback 1');
return __oldDoPostBack (eventTarget, eventArgument);
}
}
else
{
//alert('Allow Postback 2');
return __oldDoPostBack (eventTarget, eventArgument);
}
}
When an Event is triggered by a user in IE, it is set to the window.event object. The only way to see what triggered the event is by accessing the window.event object (as far as I know)
This causes a problem in ASP.NET validators if an event is triggered programmatically, like when triggering an event through jQuery. In this case, the window.event object stores the last user-triggered event.
When the onchange event is fired programmatically for a text box that has an ASP.NET validator attached to it, the validation breaks because it is looking at the element that fired last event, which is not the element the validator is for.
Does anyone know a way around this? It seems like a problem that is solvable, but from looking online, most people just find ways to ignore the problem instead of solving it.
To explain what I'm doing specifically:
I'm using a jQuery time picker plugin on a text box that also has 2 ASP.NET validators associated with it. When the time is changed, I'm using an update panel to post back to the server to do some things dynamically, so I need the onchange event to fire in order to trigger the postback for that text box.
The jQuery time picker operates by creating a hidden unordered list that is made visible when the text box is clicked. When one of the list items is clicked, the "change" event is fired programmatically for the text box through jQuery's change() method.
Because the trigger for the event was a list item, IE sees the list item as the source of the event, not the text box, like it should.
I'm not too concerned with this ASP.NET validator working as soon as the text box is changed, I just need the "change" event to be processed so my postback event is called for the text box. The problem is that the validator throws an exception in IE which stops any event from being triggered.
Firefox (and I assume other browsers) don't have this issue. Only IE due to the different event model. Has anyone encountered this and seen how to fix it?
I've found this problem reported several other places, but they offer no solutions:
jQuery's forum, with the jQuery UI Datepicker and an ASP.NET Validator
ASP.NET forums, bug with ValidatorOnChange() function
I had the same problem. Solved by using this function:
jQuery.fn.extend({
fire: function(evttype){
el = this.get(0);
if (document.createEvent) {
var evt = document.createEvent('HTMLEvents');
evt.initEvent(evttype, false, false);
el.dispatchEvent(evt);
} else if (document.createEventObject) {
el.fireEvent('on' + evttype);
}
return this;
}
});
So my "onSelect" event handler to datepicker looks like:
if ($.browser.msie) {
datepickerOptions = $.extend(datepickerOptions, {
onSelect: function(){
$(this).fire("change").blur();
}
});
}
I solved the issue with a patch:
window.ValidatorHookupEvent = function(control, eventType, body) {
$(control).bind(eventType.slice(2), new Function("event", body));
};
Update: I've submitted the issue to MS (link).
From what you're describing, this problem is likely a result of the unique event bubbling model that IE uses for JS.
My only real answer is to ditch the ASP.NET validators and use a jQuery form validation plugin instead. Then your textbox can just be a regular ASP Webforms control and when the contents change and a postback occures all is good. In addition you keep more client-side concerns seperated from the server code.
I've never had much luck mixing Webform Client controls (like the Form Validation controls) with external JS libraries like jQuery. I've found the better route is just to go with one or the other, but not to mix and match.
Not the answer you're probably looking for.
If you want to go with a jQuery form validation plugin concider this one jQuery Form Validation
Consider setting the hidden field _EVENTTARGET value before initiating the event with javascript. You'll need to set it to the server side id (replace underscore with $ in the client id) for the server to understand it. I do this on button clicks that I simulate so that the server side can determine which OnClick method to fire when the result gets posted back -- Ajax or not, doesn't really matter.
This is an endemic problem with jQuery datepickers and ASP validation controls.
As you are saying, the wrong element cross-triggers an ASP NET javascript validation routine, and then the M$ code throws an error because the triggering element in the routine is undefined.
I solved this one differently from anyone else I have seen - by deciding that M$ should have written their code more robustly, and hence redeclaring some of the M$ validator code to cope with the undefined element. Everything else I have seen is essentially a workaround on the jQuery side, and cuts possible functionality out (eg. using the click event instead of change).
The bit that fails is
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
which throws an error when it tries to get a length for the undefined 'vals'.
I just added
if (vals) {
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
}
and she's good to go. Final code, which redeclares the entire offending function, is below. I put it as a script include at the bottom of my master page or page.
Yes, this does break upwards compatibility if M$ decide to change their validator code in the future. But one would hope they'll fix it and then we can get rid of this patch altogether.
// Fix issue with datepicker and ASPNET validators: redeclare MS validator code with fix
function ValidatorOnChange(event) {
if (!event) {
event = window.event;
}
Page_InvalidControlToBeFocused = null;
var targetedControl;
if ((typeof (event.srcElement) != "undefined") && (event.srcElement != null)) {
targetedControl = event.srcElement;
}
else {
targetedControl = event.target;
}
var vals;
if (typeof (targetedControl.Validators) != "undefined") {
vals = targetedControl.Validators;
}
else {
if (targetedControl.tagName.toLowerCase() == "label") {
targetedControl = document.getElementById(targetedControl.htmlFor);
vals = targetedControl.Validators;
}
}
var i;
if (vals) {
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
}
ValidatorUpdateIsValid();
}
This is how I solved a simlar issue.
Wrote an onSelect() handler for the datepicker.
link text
In that function, called __doPostBack('textboxcontrolid','').
This triggered a partial postback for the textbox to the server, which called the validators in turn.