Data Bind to a TreeView Control in WPF?

Data Bind to a TreeView Control in WPF?

Old forum URL: forums.lhotka.net/forums/t/7066.aspx


kevnworking posted on Tuesday, June 09, 2009

Hey All,

I have a two-part question.  First, can someone turn me on to an example of databinding a child collection of objects to a TreeView control?  I've been wrestling with this for a few hours now and I can't figure it out - I THINK I'm doing it correctly but I get a big bag of nothing on the form.  I would think it would be fairly easy, something like:

<TreeView DataContext="{Binding Source={StaticResource UserModuleCollection}}">
</TreeView>

I could be way off on this - I'm new to WPF (obviously) but have found it quite easy to databind textboxes, labels and datepickers to my objects in XAML.  The treeview solution escapes me though.  I was hoping that the one line above would give me something to build on.

Second, and this is somewhat related to the first part, when needing to access a collection of child objects in a root parent object do you have to create another CslaDataProvider for that collection or is there some way to bind (in XAML) the child collection from the parents data provider?  I looked in the book but couldn't find the answer - perhaps my brain is fried from working all day.

Thanks for any help that you can offer...

Kevin

Fintanv replied on Wednesday, June 10, 2009

Take a look at the following article by Josh Smith: http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx

IMHO if you are using WPF then you make your life easier (in the long run) by following the MVVM pattern.  Others will disagree ;-)

kevnworking replied on Tuesday, June 23, 2009

Sorry for the late reply.  I did finally get this figured out, at least it displays and binds.  :0)

I will check out the article you suggested - I have noticed that every time I refresh the datasource the treeview collapses back to the root level objects instead of staying expanded where the user changed something.  I'm hoping the solution to that is in the article you suggested.

So, to answer my own question just in case someone wonders across this.  The second part of my question first - I figured this out after rereading that part of the book, the collection is exposed through it's parent class - so in this case I had a "User" class and the "Modules" class is exposed through user as a child collection.  So basically you just refer to the "Modules" collection property in User for your binding path.

Here is the XAML code I ultimately used for the treeview:
<TreeView Name="trvModules" ItemsSource="{Binding Path=Modules}">
     <TreeView.ItemTemplate>
           <HierarchicalDataTemplate ItemsSource="{Binding UserModules}">
             <StackPanel Orientation="Horizontal">
                <CheckBox Margin="1,1,5,1" IsChecked="{Binding Path=HasAccess, Converter={StaticResource IdentityConverter}, Mode=TwoWay}" />
                <TextBlock Text="{Binding Path=ModuleDescription}" />
                <TextBlock Text="(" />
                <TextBlock Text="{Binding Path=UserModuleId}" />
                <TextBlock Text=")" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

I hope this helps someone in the future.

Kevin

RockfordLhotka replied on Tuesday, June 23, 2009

Fintanv:

IMHO if you are using WPF then you make your life easier (in the long run) by following the MVVM pattern.  Others will disagree ;-)

The question is which MVVM pattern? There are several variants with different pre-conditions and consequences.

Many of the MVVM pattern variants assume an anemic Model, such as a bunch of DTO/proxy/entity objects you get back from calling a service or something like EF or L2S. Those variants require that you do a lot of work in the VM to overcome the lack of functionality in the Model, and that's fine.

However, CSLA .NET ensures that your Model is far from anemic. In fact, it is incredible rich, with the DataTable being the only thing I know of that comes close. Fortunately there are variants of MVVM where the VM exposes the Model as a property, along with various methods (commands) that can be bound to buttons, etc.

That type of MVVM implementation works really well with CSLA .NET.

On the other hand, if you use one of the "anemic model" variants of MVVM with CSLA objects, you'll have to do more work in your VM or sacrifice a lot of functionality. Your VM could have to implement and delegate (bi-directionally) all the data binding interfaces, authorization, business rule and other functionality that is built directly into CSLA.

In either case (anemic or rich Model), if your object graph is complex (parent-child-grandchild-etc) your VM can become incredibly complex very rapidly, as you try to flatten or duplicate the shape of the Model.

I've had people argue that the point of the VM is to "reshape" the Model for the UI. And I agree that if your Model was not designed using good OOD (is data-centric rather than respnsibility-driven) then your VM will probably have to do that - which is really lame, and simply means you did a crappy job with your object model.

On the other hand, if you use responsibility-driven design for your business objects, your object model should naturally follow the shape of the use case, as should the UI. Since they follow the same use case, the objects should already be the right shape.

Lots of opinion there, but that's my current way of thinking about MVVM.

Yes it is good. Some variants work really well with CSLA. Other variants cause you to do so much work that I can't possibly imagine it is of long-term benefit.

Copyright (c) Marimer LLC