René 's Weblog
...und was die Welt schon immer nicht wissen wollte
ClientID vom ServerControl automatisiert verfügbar machen
Zugriffe:1469Bewertung:2(1Bewertungen)22.07.2007 - René Drescher-Hackel

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) {
try {
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("},");
}
}
catch { }
}

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' >\r\n var ClientObjekt = new Object(); \r\n 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.

Kick it on dotnet-kicks.de
sehr gutungenügend

Ihr Kommentar zu diesem Beitrag:
your gravatar
Sollten die Eingabefelder deaktiviert sein, so aktualisieren Sie den Bestätigungscode.
Best&auml;tigungscode
Das Weblog von René Drescher-Hackel beschäftigt sich überwiegend mit Themen aus dem Bereich der Webanwendungsentwicklung mit den Themenschwerpunkten ASP.NET und C# im DOT-NET Framework 2.0 / 3.5. In der clientseitigen Entwicklung liegt der Schwerpunkt bei Javascript und jQuery. René; Drescher-Hackel hat die Prüfung zum Microsoft Certified Tecnology Specialist - .NET Framework 2.0 Web Applications abgelegt.