Click here to Skip to main content
15,557,873 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I personally do not find WPF Data Binding to be easy at all. I have
studied it up and down and then all day on tuesday. I tried experiments
to Bind as Follows.
I have a List of Person objects.
Person has Name property and a LIST of KIDs property , KID has Name property.
I Want ListBox Items to be expanders.
expander header is Bound to personList person name. ( no problem ).
TextBlock inside expander Bound to KID.name. ( problem ) .

I have attempted Heirachical Data Templates etc etc etc.
While I have met with some success by copying examples , I cannot seem
to master this Data Binding. So Can I see an example of how one of
You who have clear understanding would do this in XAML.
Instance of person list already exists in code behind.

p.s.
I get very exited when data actually appears on somthing.
Posted
Updated 17-Nov-10 1:48am
v2

Well using expanders for listbox items is not a good technique.
What you need to use is a TreeView not a listbox.

Try using TreeView. Search google on how to do data binding in a Tree view and understand each and every step.
I agree that binding in WPF is not that easy but its not difficult also!
Its been 2 months since i am learning WPF and i have learnt a lot!
Try to read a few books.
My favourites are:
Windows Presentation Foundation Unleashed by Adam Nathan
and check out Appress's Pro WPF with .net 3.5

i studied them and i found it to be very helpful! so go ahead give a fresh start!

i found a few links that might be a great help for you:
this one below uses Expander(exactly what you want!)

http://blogs.msdn.com/b/chkoenig/archive/2008/05/24/hierarchical-databinding-in-wpf.aspx

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/32a6e3c3-2ea9-43c9-b91f-282edf48b1aa

This one is a simple example:

http://www.mattlong.com.au/?p=37

Hope it helps!
 
Share this answer
 
v2
Comments
Tarun.K.S 17-Nov-10 8:05am    
http://windowsclient.net/learn/videos_wpf.aspx
o1010wanabe 17-Nov-10 20:38pm    
Great Links , Thank you so much for taking the time to answer , I truly appreciate it. The Link with the expander was known to me and was my main Source of ideas for my problem. it's not exactly what I'm trying to do. I was successfull with a treeView. but I stubornly want as I described. I will leave it Not answered for now , to see if any good Ideas show up. I am sure I can work around , just really wondered if there was Proper XAML Binding.
Tarun.K.S 18-Nov-10 1:49am    
hey i just tried using Expanders with simple data and it worked great! but i didn't use any class objects to bind with, just simple data. I will come up with a solution soon. Thanks for posting this question! i really liked the idea.
Here is a possible answer!

My Classes:

VB
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:

VB
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:
XML
<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:

VB
Imports System.Collections.ObjectModel
Public Class MyValueConverter
    Implements IValueConverter

'Convert function which takes values from list and uses casting to get the Kid class object myKid and assign it to the string myKids.

    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 value contains the Collection of kids from the property defined in 
 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) ' Get the Kid object
            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:
XML
xmlns:local="clr-namespace:ListBoxWithExpander"


and provide a key in window.resources to use the converter in textblock!:

XML
<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:
 
Share this answer
 
v3
Comments
o1010wanabe 20-Nov-10 19:59pm    
This does what I need. Thanks. I will learn IValueConverter right now.
I love this stuff. it seems you can always find a way to do what you want.
Thanks for your help.
Tarun.K.S 21-Nov-10 4:18am    
Thanks a lot for your kind words! i am also finding another way to do it!! i shall get back to you when i find a solution. Hey do vote this answer! :D
Tarun.K.S 21-Nov-10 13:22pm    
Well no success, this is the only solution that i could find! Thanks for the vote!
Hi there!
To completely solve your question, it would be great if you can show the class that you are using.

Here is how i did:

Person Class

VB
Public Class Person

    Private myname As String
    Private myage As Integer

    Public Property Name() As String
        Get
            Return myname
        End Get
        Set(ByVal value As String)
            myname = value
        End Set
    End Property

    Public Property Age() As Integer
        Get
            Return myage
        End Get
        Set(ByVal value As Integer)
            myage = value
        End Set
    End Property

    Public Sub New(ByVal myn As String, ByVal mya As Integer)
        myname = myn
        myage = mya
    End Sub

End Class


Now in the window_loaded event,
write this:

VB
Dim myoList As New ObservableCollection(Of Person)
myoList.Add(New Person("Tarun Kumar", 21))
myoList.Add(New Person("Bhupesh Kumar", 17))
ListBox2.ItemsSource = myoList



As a tip, use observablecollection instead of list because it is optimized for WPF.

Now you need to create a style together with a control template to give a new look to your listbox items:
Style for ListBoxItem

XML
<Style x:Key="TryExp" TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Expander Header="{Binding Path=Name}" Margin="3" ExpandDirection="Right" BorderThickness="1" BorderBrush="LightBlue">
                    <!--<ContentPresenter Content="{Binding Path=Age}"/>-->
                    <TextBlock Text="{Binding Path=Age}"/>
                </Expander>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>




and in the xaml for ListBox, add this:

XML
<ListBox ItemContainerStyle="{DynamicResource TryExp}" Margin="0,0,61,46" Name="ListBox2" Height="105" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="151" >
</ListBox

>

now it should work smoothly! :)
 
Share this answer
 
v2
Comments
Tarun.K.S 18-Nov-10 2:21am    
i have revised the answer by replacing the ContentPresenter with TextBlock.
o1010wanabe 19-Nov-10 4:42am    
Exellent , I also like the idea and have been experimenting further. I have almost got it. I will post my code as an answer , to better explain my idea.
o1010wanabe 19-Nov-10 5:06am    
I have to rush off to work now but as a reminder ( and I have managed to )
person Name is bound to expander header. and a List property of Kids that is inside person - bound to the expander body.
when I return I will show you my results, they are not perfect , but not bad.
Tarun.K.S 19-Nov-10 6:16am    
Ohkay that's great! Waiting eagerly to see the answer! by the time i will try with a new class as you said.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900