Here is a possible answer!
My Classes:
Imports System.Collections.ObjectModel
Public Class Person
Dim mname As String
Dim mkids As New ObservableCollection(Of Kid)
Public Property PName() As String
Get
Return mname
End Get
Set(ByVal value As String)
mname = value
End Set
End Property
Public Property Kids() As ObservableCollection(Of Kid)
Get
Return mkids
End Get
Set(ByVal value As ObservableCollection(Of Kid))
mkids = value
End Set
End Property
Public Sub New(ByVal _nm As String, ByVal _kids As ObservableCollection(Of Kid))
mname = _nm
mkids = _kids
End Sub
End Class
Public Class Kid
Dim mkname As String
Public Property KName() As String
Get
Return mkname
End Get
Set(ByVal value As String)
mkname = value
End Set
End Property
Public Sub New(ByVal _kname As String)
mkname = _kname
End Sub
End Class
The above class has a Constructor to load values as you will see down how i have used it.
My window_loaded event:
Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Dim perList As New ObservableCollection(Of Person)
Dim kidList1 As New ObservableCollection(Of Kid)
kidList1.Add(New Kid("AAA"))
kidList1.Add(New Kid("BBB"))
perList.Add(New Person("Person 1", kidList1))
Dim kidList2 As New ObservableCollection(Of Kid)
kidList2.Add(New Kid("CCC"))
kidList2.Add(New Kid("DDD"))
perList.Add(New Person("Person 2", kidList2))
ListBox1.ItemsSource = perList
End Sub
So i have created a collection of kids without creating objects for each kid.
Item template:
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Name="myExpander" ExpandDirection="Right">
<Expander.Header>
<TextBlock Text="{Binding Path=PName}"/>
</Expander.Header>
<Expander.Content>
<TextBlock Text="{Binding Path=Kids, Converter={StaticResource MyConv}}"/>
</Expander.Content>
</Expander>
</DataTemplate>
</ListBox.ItemTemplat
e>
I have created a Value Converter class to convert the collection of kids to string, so the textblock can get that string.
Converter Class:
Imports System.Collections.ObjectModel
Public Class MyValueConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
the property of person class
Dim myList As ObservableCollection(Of Kid) = value
Dim myKids As String = String.Empty
Dim myKid As Kid
For i As Integer = 0 To myList.Count - 1
myKid = TryCast(myList.Item(i), Kid)
myKids = myKids & myKid.KName & " "
Next
Return myKids
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Throw New NotImplementedException("Convert Back not implemented")
End Function
End Class
So the above code returns a string by retrieving the kid's name in the collection.
The xaml should recognize this class so we have to provide a namespace of the current assembly:
xmlns:local="clr-namespace:ListBoxWithExpander"
and provide a key in window.resources to use the converter in textblock!:
<Window.Resources>
<local:MyValueConverter x:Key="MyConv"/>
</Window.Resources
>
So the we will use the key as static resource and assign it in the textblock!!
That's it!! :-D PHEW!
And sorry that the code is in VB but i think there won't be any problem in converting.
U can use this to convert:
http://www.developerfusion.com/tools/convert/vb-to-csharp/[
^]
Now it should work fine! :thumbsup: