ClientID vom ServerControl automatisiert verfügbar machen

Zugriffe: 5563 starstarstarstarstarstarstarstarstarstar Bewertung:2,69 (13 Bewertungen) 22.07.2007

Im Rahmen der Webentwicklung steht man immer wieder vor dem Problem, die richtige ClientID nach dem Rendern des HTML zu ermitteln. Der eine (aber unschönste Weg!) ist, über die Quellcodeansicht die zahlreichen ClientIDs zu ermitteln und dann zum Beispiel hartcodiert im Javascript einzufügen.
Ein weiterer Weg ist über die Inlinecodeanweisung <% = ServerControlID.ClientID %> den Wert zu holen. Problemiliatisch ist dieses Vorgehen aber für den Fall, wenn man über eine externe Scriptdatei im Code die Information benötigt. Hier bekommt man dann solche Auskünfte:

alertcontrol

Einen anderen Weg kann man gehen, wenn man auf JSON zurückgreift. Hier erlangt man fast vollständige Flexibilität über seine Clientobjekte.
Zunächst habe ich die Webseite nach allen Controls, die das ID-Attribute gesetzt haben, untersucht.

private void SetClientIDs( ControlCollection ctls) {
          foreach ( Control ctrl in ctls) {
             if (ctrl.HasControls())
                 SetClientIDs(ctrl.Controls);
             else
                 WriteControlIDtoSb(ctrl);
          }
}

In der Methode WriteControlIDtoSb(ctrl) erstelle ich dann den JSON-String:

private void WriteControlIDtoSb( Control ctrl) {

if (ctrl.ID.ToString() != string.Empty) {
      sb.AppendFormat( "\"{0}\": {{" , ctrl.ID);
      sb.AppendFormat( "\"id\" : (\"{0}\"), ", ctrl.ClientID);
      sb.AppendFormat( "\"style\" : document.getElementById(\"{0}\").style, ", ctrl.ClientID);
      sb.AppendFormat("\"className\" : document.getElementById(\"{0}\").className, ", ctrl.ClientID);
   if (ctrl.GetType().Equals(typeof(DropDownList)) ||
      ctrl.GetType().Equals(typeof(HtmlSelect))) {
   if (ctrl.GetType().Equals(typeof(DropDownList)) && ((DropDownList)ctrl).Items.Count > 0) {
      sb.Append("\"Items\" : [ ");
   for (int i = 0; i < ((DropDownList)ctrl).Items.Count; i++) {
      sb.Append("{");
      sb.AppendFormat("\"value\" : document.getElementById(\"{0}\").options[{1}].value, ", ctrl.ClientID, i);
      sb.AppendFormat("\"text\" : document.getElementById(\"{0}\").options[{1}].text, ", ctrl.ClientID, i);
      sb.AppendFormat("\"selected\" : document.getElementById(\"{0}\").options[{1}].selected }}", ctrl.ClientID, i);
         if (i < ((DropDownList)ctrl).Items.Count - 1)
            sb.Append(", ");
   }
   sb.Append("] , ");
}
if (ctrl.GetType().Equals(typeof(HtmlSelect)) && ((HtmlSelect)ctrl).Items.Count > 0) {
   sb.Append("\"Items\" : [ ");
   for (int i = 0; i < ((HtmlSelect)ctrl).Items.Count; i++) {
      sb.Append("{");
      sb.AppendFormat("\"value\" : document.getElementById(\"{0}\").options[{1}].value, ", ctrl.ClientID, i);
      sb.AppendFormat("\"text\" : document.getElementById(\"{0}\").options[{1}].text, ", ctrl.ClientID, i);
      sb.AppendFormat("\"selected\" : document.getElementById(\"{0}\").options[{1}].selected }}", ctrl.ClientID, i);
         if (i < ((HtmlSelect)ctrl).Items.Count - 1)
            sb.Append(", ");
   }
   sb.Append("] , ");
}
   sb.AppendFormat("\"selectedText\" : document.getElementById(\"{0}\").options[document.getElementById(\"{0}\").selectedIndex].text,", ctrl.ClientID);
   sb.AppendFormat("\"selectedValue\" : document.getElementById(\"{0}\").options[document.getElementById(\"{0}\").selectedIndex].value,", ctrl.ClientID);
   }
   else {
      sb.AppendFormat("\"value\" : document.getElementById(\"{0}\").value, ", ctrl.ClientID);
   }
   sb.AppendFormat("\"onchange\" : document.getElementById(\"{0}\").onchange, ", ctrl.ClientID);
   sb.AppendFormat("\"onclick\" : document.getElementById(\"{0}\").onclick ", ctrl.ClientID);
   sb.Append("},");
}

Hierbei habe ich den JSON-String so aufbereitet, dass ich nur bestimmte Eigenschaften im direkten Zugriff habe. Die Methode ist dabei beliebig erweiterbar und soll hier nur einen möglichen Ansatz wiedergeben.
Zum Schluss muss das ganze noch zum Client transportiert werden:

ClientScript.RegisterStartupScript(this.Page.GetType(), 
"ClientObjekte", string.Format("<script type='text/javascript' >
   var ClientObjekt = new Object();
   eval('ClientObjekt = {{{0}}}}}');\r\n</script>", 
   sb.ToString().Substring(0, sb.ToString().Length - 2)));

Auf der Clientseite kann ich dann auf meine Serversteuerelemente direkt zugreifen:

ClientObjekt.UCTextBox1.value - gibt den Text der TextBox "UCTextBox1" zurück.
ClientObjekt.dropdownControl.selectedText - gibt den ausgewählten Text der DropDownListe "dropdownControl" zurück.
ClientObjekt.dropdownControl.Items[0].text - gibt den Text des ersten Elements der DropDownListe "dropdownControl" zurück.

Der Debugger zeigt einen schönen Gesamtüberblick:

debugview

Update: Peter Bucher zeigt in seinem Weblog, wie das ganze sich noch umsetzen läst.


Neuen Kommentar verfassen

Bestätigungscode