De flesta vet väl att listboxarnas (och comboboxarnas) items är av typen object i .Net. Ofta hämtar jag data från en webservice och får t.ex ett dataset med en produkttabell i och vill därefter fylla en listbox med alla produkter i tabellen.
Det som visas i listrutan är det man får fram om man kör .ToString() på objektet. I de flesta fall, t.ex. om man har en struktur eller tabell från ett dataset så är det namnet på objekttypen man får fram om man kör ToString() på objektet, alltså fungerar det inte direkt att putta in detta.
Om man t.ex. skapar en struktur och använder denna för att fylla en listruta:
Public Class Form1
Public Structure Customer
Public CustomerID As Integer
Public FirstName As String
Public LastName As String
End Structure
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim item As New Customer
item.CustomerID = 0
item.FirstName = "Stefan"
item.LastName = "Karlsson"
ListBox1.Items.Add(item)
End Sub
End Class
Så blir resultatet detta, inte precis vad man ville ha:
I strukturfallet så är detta inget problem, man overridar bara ToString() med en egen ToString() så kan man putta in vad man vill:
Public Structure Customer
Public CustomerID As Integer
Public FirstName As String
Public LastName As String
Public Overrides Function ToString() As String
Return Me.FirstName & " " & Me.LastName
End Function
End Structure
På så vis så visar listrutan snällt det man vill:
Men om strukturen kommer från en klass du inte kan påverka? Låt säga att vi har en klass vi inte har möjlighet att ändra i. clsCustomer heter den och den har en funktion som heter GetCustomers som returnerar en lista av kunder av typen Customer (strukturen vi hade ovan).
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim CustomerClass As New clsCustomer
ListBox1.DataSource = CustomerClass.GetCustomer 'returnerar en List(Of Customer)
End Sub
I ovanstående fall så har vi inte möjlighet att gå in i koden och overridea ToString. Det går inte heller att använda Extensions för att lägga till ToString på den befintliga strukturen då Extensions inte tillåter att man ändrar i befintligt gränssnitt, bara utökar den.
Det är här man kan använda magin av partial klasser och partial structures
Genom att definiera upp en partial klass av typen clsCustomer och sedan inuti den definiera upp en partial struktur av typen Customer så kan vi overrida strukturens ToString() och få den att bete sig som vi vill:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim CustomerClass As New clsCustomer
ListBox1.DataSource = CustomerClass.GetCustomer 'returnerar en List(Of Customer)
End Sub
End Class
Partial Class clsCustomer
Partial Structure Customer
Public Overrides Function ToString() As String
Return Me.FirstName & " " & Me.LastName
End Function
End Structure
End Class
När man skriver partialklassen i editorn så får man intellisense på vilka klasser man kan arbeta med, när man sedan skriver Partial Structure så får man upp de befintliga strukturerna i clsCustomer så det är lätt att koda på det här viset.
Det vi gjort nu är att vi hookat in på en befintlig klass, och befintlig struktur och overrideat ToString på strukturen, vilket gör att listboxen kommer att visa det vi vill.
Detta är även praktiskt om man har objekt som inte innehåller det man vill, t.ex. så hade ju customer-objektet FirstName och LastName, men vi ville ju att listrutan skulle innehålla fulständigt namn, det fanns inte med i objektet. På samma sätt skulle man kunna lägga på summeringar osv i orderobjekt m.m.
Om man arbetar i VS2008 så har man möjlighet att använda Extensions för att t.ex. utöka ett objekt med en summeringsfunktion och om man tänker efter lite så är Extensions ihop med Partial ruggigt starka verktyg som går att använda dagligen på många ställen för att underlätta implementation av externa objekt (och mycket annat också så klart).