This is a migrated thread and some comments may be shown as answers.

Sub-GridView (details) databinding MVVM

4 Answers 459 Views
GridView
This is a migrated thread and some comments may be shown as answers.
David Sandor
Top achievements
Rank 1
David Sandor asked on 18 Apr 2010, 01:41 PM
Hi,  This may be a WPF Databinding question but I think this should be simple.

I have a RadGridView that displays a collection of objects and allows a user to drill down into a subcollection of the databound object.  I use the following XAML to define the GridView:

 <telerik:RadGridView ItemsSource="{Binding L2SClasses}" ColumnsWidthMode="Fill" telPres:StyleManager.Theme="Vista" CanUserInsertRows="False" CanUserDeleteRows="False" IsReadOnly="True" 
                                         SelectedItem="{Binding SelectedClass}" AutoGenerateColumns="False"  ShowGroupPanel="False" > 
                        <telerik:RadGridView.Columns> 
                            <telerik:GridViewToggleRowDetailsColumn /> 
                            <telerik:GridViewDataColumn Header="Class Name">  
                                <telerik:GridViewDataColumn.CellTemplate> 
                                    <DataTemplate> 
                                        <TextBlock Text="{Binding ClassName}" /> 
                                    </DataTemplate> 
                                </telerik:GridViewDataColumn.CellTemplate> 
                            </telerik:GridViewDataColumn> 
                        </telerik:RadGridView.Columns> 
                        <telerik:RadGridView.RowDetailsTemplate> 
                            <DataTemplate> 
                                <telerik:RadGridView ItemsSource="{Binding Properties}" CanUserInsertRows="False" CanUserDeleteRows="False" IsReadOnly="True" ColumnsWidthMode="Fill" 
                             telPres:StyleManager.Theme="Vista" MaxWidth="600" ShowGroupPanel="False" SelectedItem="{Binding SelectedProperty,Mode=TwoWay}">  
                                    <telerik:RadGridView.Columns> 
                                        <telerik:GridViewDataColumn Header="Name">  
                                            <telerik:GridViewDataColumn.CellTemplate> 
                                                <DataTemplate> 
                                                    <TextBlock Text="{Binding Name}" /> 
                                                </DataTemplate> 
                                            </telerik:GridViewDataColumn.CellTemplate> 
                                        </telerik:GridViewDataColumn> 
                                        <telerik:GridViewDataColumn Header="Type">  
                                            <telerik:GridViewDataColumn.CellTemplate> 
                                                <DataTemplate> 
                                                    <TextBlock Text="{Binding Type}" /> 
                                                </DataTemplate> 
                                            </telerik:GridViewDataColumn.CellTemplate> 
                                        </telerik:GridViewDataColumn> 
                                        <telerik:GridViewColumn> 
                                            <telerik:GridViewColumn.CellTemplate> 
                                                <DataTemplate> 
                                                    <Button Content="Add to Model >>" Name="btnAddToModel" Click="btnAddToModel_Click" /> 
                                                </DataTemplate> 
                                            </telerik:GridViewColumn.CellTemplate> 
                                        </telerik:GridViewColumn> 
                                    </telerik:RadGridView.Columns> 
                                </telerik:RadGridView> 
                            </DataTemplate> 
                        </telerik:RadGridView.RowDetailsTemplate> 
                    </telerik:RadGridView> 

The SelectedItem of the master GridView works great.  When a row is selected the SelectedItem is set in my ViewModel.  The problem is that the same functionality is not happening in the child GridView.  I think I need to define the DataContext on the sub GridView somehow but I am unsure of how to do this.  I would like the sub-GridView (child) to set the SelectedProperty property of my ViewModel but it does not work. 

Any assistance would be greatly appreciated!

Thanks,
David Sandor

4 Answers, 1 is accepted

Sort by
0
Rossen Hristov
Telerik team
answered on 19 Apr 2010, 12:01 PM
Hello David Sandor,

The DataContext of the row details element (your child grid in this case) is automatically set to the data item of the respective parent grid row (I guess it is called a L2SClass). So for example, if your business object has a property named "Properties" your details grid can be bound to it automatically, like I see that you have done in your example.

In case you want to change this behavior, you might need to create a custom view-model (containing both the "Properties" and a "SelectedProperty" properties) and set the DataContext if the DetailsElement to this new view model. You can do this in the LoadingRowDetails event of the parent grid.

From the event arguments you can take both the DetailsElement (RadGridView in your case) and the DataContext. By default this DataContext will be the parent data item (I guess it is called a L2SClass). You can attach to this event and see what you are receiving from the event argument with the debugger. Create your custom view model by passing in the L2SClass and the custom view model instance as the new DataContext of the DetailsElement. This will enable the child grid to bind both its ItemsSource to YourViewModel.Properties and its SelectedItem to YourViewModel.SelectedProperty:

ChildGrid.ItemsSource <-> YourViewModel.Properties -> this will return the L2SClass.Properties
ChildGrid.SelectedItem <-> YourViewModel.SelectedProperty -> this will be a property which will help you track down the selected item.

I hope this helps.

Greetings,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
David Sandor
Top achievements
Rank 1
answered on 19 Apr 2010, 02:00 PM
Hi Ross,

Thank you for your detailed reply, it is very helpful.

I am also wondering if I can set the SelectedItem of the child GridView to a binding that will databind to a property on the parent's datacontext?

Thanks,
David Sandor


0
David Sandor
Top achievements
Rank 1
answered on 19 Apr 2010, 02:21 PM
Hi Ross,

I found a solution to my problem which was pretty simple.  I thought I would share it with the community because I have seen a LOT of posts on the internet about this type of databinding.  It turns out my knowledge of RelativeSource databinding is my fault here. 

SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Page}}, Path=DataContext.MyProperty}" 

So by using a RelativeSource databinding I acheived what I needed.  The line of code above will perform a 'find' until it finds a UIElement of type 'Page' (use 'UserControl' or 'Window' depending on the XAML root element type: <Page .... in my case).  Once the element is found (if it is found) the path will be relative to the element found. 

What this means is that my databinding will enumerate from the child GridView up until it finds a UIElement of type Page.  That becomes my Binding and I can use the Path to specify the DataContext of the Page object and then my property (in this case I used a property name of MyProperty).  So in my first post the line of code would be:

SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Page}}, Path=DataContext.SelectedProperty}"   
 

I do not have time to test it right now but I think I could narrow the relative source scope to RadGridView instead of Page, but this is working for me now and performance is not an issue with this code.

I hope this helps someone else.

-David Sandor
0
Rick Glos
Top achievements
Rank 1
answered on 16 Dec 2010, 06:31 PM
David, thanks for your last post about RelativeSource and finding the DataContext.

I have a similar situation with a RadGridView and RowDetailsTemplate in which the user can drill down 3 levels and view other grids, and grids inside those grids (Sales -> Invoices -> Invoice Lines).  In our UI we allow the user to turn filter/grouping on and off.  We have this property set in the ViewModel.  We are using Prism and the View doesn't have knowledge of the ViewModel so it is not in the XAML anywhere.

I was able to bind all the nested child RadGridView.IsFilteringAllowed properties by using your example.  Here's mine:

IsFilteringAllowed="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.IsAdvancedUserInterfaceOn}"
Tags
GridView
Asked by
David Sandor
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
David Sandor
Top achievements
Rank 1
Rick Glos
Top achievements
Rank 1
Share this question
or