简体   繁体   中英

ASP.NET Server Control client-side event handling

I have a question regarding ASP.NET server controls with client functionalities. I want to improve the client-side event handling: when a child client-control fires an event, I want the parent client-control to be directly notified.

Let's assume we have two server controls, MyWindow and MyTextBox. Both are client-side objects of type "Sys.UI.Control".

The MyTextBox is a child of MyWindow:

public class MyWindow : Control, IScriptControl
{
   private MyTextBox _mtb;
   //....
   protected override void CreateChildControls()
   {
       _mtb = new MyTextBox();
       _mtb.ID = "MTB";
       _mtb.OnClientTextChanged = "OnClientTextChanged";
       Controls.Add(_mtb);
   }

   //...
   public IEnumerable<ScriptDescriptor> GetScriptDescriptors()
  {
     ScriptControlDescriptor descriptor = new ScriptControlDescriptor("Test.MyWindow", ClientID);
     descriptor.AddComponent("myTextBox", _mtb.ClientID);
     yield return descriptor;
  }

client-side:

  function OnClientTextChanged(sender, args) {
      alert('test')
  }

Now, whenever the text of the textbox changes, the client-event is fired and calls the function "OnClientTextChanged".

What I want is to notify the client object of "MyWindow". I could do that this way:

  function OnClientTextChanged(sender, args) {
      $find("MyWindow").textBoxChangedItsText();
  }

But how can I notify the client object of MyWindow directly without using this global javascript function? What I tested was

_mtb.OnClientTextChanged = string.Format("($find('{0}')).textBoxChangedItsText", ClientID);

but I the "textBoxChangedItsText" function inside the client object can not access the object itself - "this" is the function itself but not the object which I would find using "$find("MyWindow")"

I hope the question is clear to persons with knowledge in client-side enabled AJAX server side controls.

Thanks!

Edit: Using this event hander on the client-side works:

server-side:

 _mtb.OnClientTextChanged = string.Format(" ($find('{0}')).textBoxChangedItsTextDelegate", ClientID);

client-side:

Test.MyWindow = function (element) {
   Test.MyWindow.initializeBase(this, [element]);
   this.textBoxChangedItsTextDelegate= Function.createDelegate(this, function (sender, e) {
      this.textBoxChangedItsText();
   });
};

Test.MyWindow.prototype = {
   initialize: function () {
      Test.MyWindow.callBaseMethod(this, 'initialize');
   },
   textBoxChangedItsText: function () {
      alert(this.get_id());
   },
   dispose: function () {
      Test.MyWindow.callBaseMethod(this, 'dispose');
   }
};

What I still don't like is the attaching to the event server-side with the $find in the event handler: _mtb.OnClientTextChanged = string.Format(" ($find('{0}')).textBoxChangedItsTextDelegate", ClientID);

I suppose that you need to define events as it basically done in ASP.NET Client Side controls. So it is necessary to add the following to your MyTextBox client side object prototype:

add_textChanged: function(handler) {
    this.get_events().addHandler('shown', handler);
}
remove_TextChanged: function (handler) {
    this.get_events().removeHandler('textChanged', handler);
}
raise_textChanged: function (eventArgs) {
    var handler = this.get_events().getHandler('textChanged');
    if (handler) {
        handler(this, eventArgs);
    }
}

This will define client side event to which client code (parent controls or page) can subscribe and perform required actions. To raise this event in your MyTextBox you can use the code like this:

this.raise_textChanged(Sys.EventArgs.Empty);

And to use this event in MyWindow client side object you need to modify your code to the following:

Test.MyWindow = function (element) {
   Test.MyWindow.initializeBase(this, [element]);

   this._myTextBoxID = null;
   this._onTextChanged$delegate = Function.createDelegate(this, this._onTextChanged);
};

Test.MyWindow.prototype = {
   initialize: function () {
      Test.MyWindow.callBaseMethod(this, 'initialize');

      $find(this._myTextBoxID).add_textChanged(this._onTextChanged$delegate);
   },

   _onTextChanged: function(sender, eventArgs) {
        // Perform required actions.
        // this - will be instance of the this client side object.
   }

   dispose: function () {
        $find(this._myTextBoxID).remove_textChanged(this._onTextChanged$delegate);

      Test.MyWindow.callBaseMethod(this, 'dispose');
   }
};

Note: in the example provided I used this._myTextBox which equals to client id of the child MyTextBox control. You can use property "myTextBox" without performing $find because you initialize it using descriptor.AddComponent("myTextBox", _mtb.ClientID);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM