View previous topic :: View next topic |
Author |
Message |
EntityDev
Joined: 07 Apr 2016 Posts: 40
|
Posted: Sun Apr 17, 2016 7:58 pm Post subject: ObjectRowBinding as child of a row |
|
|
This sort of question is asked in various ways in the forum. I have searched, but didn't find an answer that quite fits my scenaro. My current effort is to do a mix of Object and Programmatic databinding. My question - is it possible to display data like this:
Root Row (IList) (ObjectRowBinding)
----Object 1
--------ObjectCollection 1 (IList) (ObjectRowBinding)
------------Object 1
------------Object 2
--------ObjectCollection 2 (IList) (ObjectRowBinding)
------------Object 1
------------Object 2
----Object 2
--------ObjectCollection 1 (IList) (ObjectRowBinding)
------------Object 1
------------Object 2
--------ObjectCollection 2 (IList) (ObjectRowBinding)
------------Object 1
------------Object 2
In my reading archived threads, it seems this can be done, but the subject has usually involved DataSets and has been different in scope. If this is possible, please tell me which events to handle (VirtualTree, Row, Binding or otherwise) and which Types to use. I code in VB.Net.
Thank you. |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Mon Apr 18, 2016 1:24 am Post subject: |
|
|
You can display any hierarchical data structure in Virtual Tree. However if your underlying data is in a different form then you will need to create a data model that Virtual Tree can bind to. For instance if you have a Car class that has two properties EngineParts and BodyParts that both return lists of Parts. You could display a tree like:
Code: | Car
- Engine Part 1
- Engine Part 2
|
Or a tree like:
Code: | Car
- Body Part 1
- Body Part 2
|
By using object binding and setting the ChildProperty of the Car binding to either the EngineParts or BodyParts property.
If however you wanted to display:
Code: | Car
- Engine Parts
-- Engine Part 1
-- Engine Part 2
- Body Parts
-- Body Part 1
-- Body Part 2
|
Then you need to provide Virtual Tree with a data model to bind to that reflects this structure. In this case you need to provide a list of child objects for the Car object that corresponds to what you want to display. So you might create a CarProperty class to represent this like:
Code: |
Public Class CarProperty
Public Sub New(ByVal sName as String, ByVal sParts as IList)
Name = sName
Parts = sParts
End Sub
Public Property Name As String
Public Property Parts As IList
End Class
|
You can create Object Bindings to define how each of the individual items (Car, CarProperty and Parts) are displayed in the tree and use Programmatic binding to define the parent/child relationships.
You would handle the GetChildren event something like:
Code: | Private Sub _virtualTree_GetChildren(ByVal sender As Object, ByVal e As GetChildrenEventArgs) Handles _virtualTree.GetChildren
If TypeOf e.Row.Item Is Car Then
Dim sCar As Car = e.Row.Item
Dim sList As New List(Of CarProperty)
sList.Add(New CarProperty("Engine Parts", sCar.EngineParts))
sList.Add(New CarProperty("Body Parts", sCar.BodyParts))
e.Children = sList
ElseIf TypeOf e.Row.Item Is PartList Then
e.Children = e.Row.Item
End If
End Sub |
_________________ Infralution Support |
|
Back to top |
|
|
EntityDev
Joined: 07 Apr 2016 Posts: 40
|
Posted: Mon Apr 18, 2016 6:39 am Post subject: |
|
|
Indeed, I have studied the ProgrammaticBinding sample, and I see how the Part class is constructed with both child and parent properties. I was trying to achieve something similar to the root row at each level of the tree. I see that the .Name property of your proposed 'Property' class should provide that. I wrote a class combining the elements necessary and handled the tree's GetChildren event. This is very close, but I get no child rows in the tree for the .Children property of the surrogate class.
Can you spot what the problem is? The tree is configured with just a main column (Caption = "Item") and an ObjectRowBinding (.ChildProperty = Me). I'm setting the binding type programmatically.
Code: | Public Class JobListProperty
Private m_Caption As String
Private m_Children As IList
Public Property Caption As String
Get
Return m_Caption
End Get
Set(value As String)
m_Caption = value
End Set
End Property
Public Property Children As IList
Get
Return m_Children
End Get
Set(value As IList)
m_Children = value
End Set
End Property
Public Sub New()
End Sub
Public Sub New(caption As String, children As IList)
m_Caption = caption
m_Children = children
End Sub
Public Overrides Function ToString() As String
Return m_Caption
End Function
End Class |
Code: | Private Sub JobListVirtualTree_GetChildren(sender As Object, e As Infralution.Controls.VirtualTree.GetChildrenEventArgs) Handles JobListVirtualTree.GetChildren
If TypeOf e.Row.Item Is Job Then
Dim job = DirectCast(e.Row.Item, Job)
If job.JobLabor.Any OrElse job.Technicians.Any Then
Dim properties As New List(Of JobListProperty)
If job.JobLabor.Any Then properties.Add(New JobListProperty With {.Caption = "Labor", .Children = job.JobLabor})
If job.Technicians.Any Then properties.Add(New JobListProperty With {.Caption = "Technicians", .Children = job.Technicians})
e.Children = properties
End If
ElseIf TypeOf e.Row.Item Is IList Then
e.Children = e.Row.Item
End If
End Sub |
|
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Mon Apr 18, 2016 7:44 am Post subject: |
|
|
Just to confirm - you get JobProperties displaying but not the children of this object?
Sorry I think my sample code was misleading. If you handle the GetChildren event then you take full responsibility for that part of the binding. So you must handle all the expected types (and return children for them if required). So in your case you need to add an elseif clause to handle the JobListProperty eg
Code: |
If TypeOf e.Row.Item Is Job Then
...
ElseIf TypeOf e.Row.Item Is IList Then
e.Children = e.Row.Item
ElseIf TypeOf e.Row.Item is JobListProperty Then
e.Children = DirectCast(e.Row.Item, JobListProperty).Children
End If
|
Alternatively you can use the default object bindings for all types other than Job eg
Code: | If TypeOf e.Row.Item Is Job Then
...
Else
Dim binding As RowBinding = _virtualTree.GetRowBinding(e.Row)
e.Children = binding.GetChildrenForRow(e.Row)
End If |
Your JobListProperty Object binding would therefore need to have the ChildProperty set to "Children" _________________ Infralution Support |
|
Back to top |
|
|
EntityDev
Joined: 07 Apr 2016 Posts: 40
|
Posted: Mon Apr 18, 2016 12:08 pm Post subject: |
|
|
That is correct, the tree was displaying the .ToString property of JobListProperty, but nothing deeper. Your first approach works well, thank you very much.
The alternate approach does not. I used the alternate block of code and set my existing ObjectRowBinding.ChildProperty = "Children". The tree only displays the root row (with the binding's main column Format string). I would like to understand your object model, and eventually I will.
It occurs to me that you probably assume the datasource of the tree is a collection (list) of JobListProperty, because I omitted that information. It is actually a SortableBindingList(Of Job), mostly because that's the Type I've been using all along...
I was hoping to have sorting handled by your object. So, I thought an ITypedList as the tree's datasource, along with all ITypedList .Children (they are), would be appropriate. I have little doubt my thinking on this is flawed.
Is it conventional to instead use an IList of the 'property' class as the VirtualTree's datasource? |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Mon Apr 18, 2016 12:20 pm Post subject: |
|
|
For the alternative solution to work the Object Bindings for the other classes (other than Job) must define the ChildProperty. Since only the root row is displayed it seems that you haven't defined the ChildProperty for the root row binding - it should be set to "this" or "Me" since the root item is itself the list of children. _________________ Infralution Support |
|
Back to top |
|
|
EntityDev
Joined: 07 Apr 2016 Posts: 40
|
Posted: Mon Apr 18, 2016 1:27 pm Post subject: |
|
|
Thank you, I'll work with both methods. |
|
Back to top |
|
|
|