Eine doch lästige und unschöne Einschränkung bei der DropDownList ist doch, dass man nur ein Feld der DataSource an das Control binden kann.

Oft will man halt aber mehr als nur ein Feld darstellen:

Kategorie A: 3 Fahrzeuge

Kategorie B: 11 Fahrzeuge

Kategorie C: 1 Fahrzeug

Natürlich geht das relativ problemlos, z.B. mittels String-Concatenation, ist aber doch lästig, wenn man sonst alles schön über direktes DataBinding lösen könnte – zumal das Control ja auch einen FormatString zur Steuerung der Ausgabe entgegennimmt.

Eine Ableitung der DropDownList zu bauen, die das kann, ist zum Glück keine Kunst. Nachfolgend das Beispiel mit einer DropDown-List, die ListBox verhält sich analog.

Zuerst erstellt man sich also eine Klasse, die von DropDownList erbt:

   1: public class MultiColumnDropDownList : DropDownList

 

Die DropDownList nimmt den Namen des anzuzeigenden DataSource-Feldes im Property DataTextField auf. Ich benutze das Property gleich auch für meine Zwecke, lasse aber mehrere Angaben, getrennt durch ein Semikolon zu.

Die einzige Methode dies es dann zu überschreiben gilt ist PerformDataBinding. Dort kriegt man als Parameter die DataSource praktisch als IEnumerable.

   1: protected override void PerformDataBinding(System.Collections.IEnumerable dataSource)

Die eigentliche Implementation ist dann denkbar simpel:

   1: foreach (Object obj in dataSource)
   2: {
   3:     string[] textFieldsValues = new string[textFields.Length];
   4:     for (int i = 0; i < textFields.Length; i++)
   5:     {
   6:         textFieldsValues[i] = DataBinder.GetPropertyValue(obj, textFields[i].Trim()).ToString();
   7:     }
   8:  
   9:     ListItem li = new ListItem();
  10:     li.Text = string.Format(list.DataTextFormatString, textFieldsValues);
  11:     li.Value = DataBinder.GetPropertyValue(obj, list.DataValueField);
  12:     list.Items.Add(li);
  13: }

In Zeile 6 wird mittels der DataBinder-Klasse der Wert aus der DataSource gelesen. Hat den Vorteil, dass man sich nicht darum kümmern muss, was denn nun für eine DataSource dahinter steckt. Der Rest ist wohl selbsterklärend.

Eingebunden in einer aspx-Seite sieht dann das so aus:

   1: <NN:MultiColumnDropDownList  ID="ddlMulti" runat="server" 
   2:             DataSourceID="ObjectDataSource1" DataTextField="Name;PreName" 
   3:             DataValueField="Id" DataTextFormatString="{0} {1}" />

Und als Ausgabe:

greenshot_2008-10-02_20-38-46

Download der Sourcen