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

Data binding problem with SelectedItem in child grid

18 Answers 1089 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Craig
Top achievements
Rank 1
Craig asked on 13 Feb 2013, 05:31 PM
Hello,
I have a problem binding the SelectedItem of a child grid to a property on my view model. I've included the relevant XAML at the bottom.

The data binding of the SelectedItem of the parent Group finds the view model property okay. I've tried to use the same approach for SelectedItem of the child grid but a get a binding error 'BindingExpression path error: 'SelectedGroupItem' property not found on 'object' ''Group' '. Group is the type of the child object so I can understand why it complains.

//Groups defined in the view model
public ObservableCollection<Group> Groups { get;set;}
...
 
//Group class
public class Group
{
    public Group()
    {
        GroupItems = new List<GroupItem>();
    }
    public string GroupName { get; set; }
    public List<GroupItem> GroupItems { get; set; }
}


How do I change the SelectedItem="{Binding SelectedGroupItem}" data binding expression to refer to the view model as the parent grid has done?

Craig


<Grid.Resources>
  <DataTemplate x:Key="GroupItemTemplate">
    <telerik:RadGridView ItemsSource="{Binding GroupItems, Mode=TwoWay}" Name="itemsGrid"
   ShowGroupPanel="False"  AutoGenerateColumns="False" SelectedItem="{Binding SelectedGroupItem}">
      <telerik:RadGridView.Columns>
        <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Item Name" Width="*" />
        <telerik:GridViewDataColumn DataMemberBinding="{Binding Description}" Header="Item Name" Width="*" />
      </telerik:RadGridView.Columns>
    </telerik:RadGridView>
  </DataTemplate>
</Grid.Resources>
 
<telerik:RadGridView Name="groupsGrid" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left"
  VerticalAlignment="Stretch" Width="Auto" ItemsSource="{Binding Groups, Mode=TwoWay}"
  AutoGenerateColumns="False" ShowGroupPanel="False" ShowInsertRow="True" RowHeight="23"
  RowIndicatorVisibility="Collapsed" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
  SelectedItem="{Binding SelectedGroup}"
  HierarchyChildTemplate="{StaticResource GroupItemTemplate}">
  <telerik:RadGridView.Columns>
    <telerik:GridViewDataColumn DataMemberBinding="{Binding GroupName}" Header="Group Name" Width="*"/>
  </telerik:RadGridView.Columns>
  <telerik:RadGridView.ChildTableDefinitions>
    <telerik:GridViewTableDefinition />
  </telerik:RadGridView.ChildTableDefinitions>
</telerik:RadGridView>

18 Answers, 1 is accepted

Sort by
0
Maya
Telerik team
answered on 14 Feb 2013, 07:21 AM
Hello Graig,

The DataContext of the child grid is the corresponding data item - that is why it looks for SelectedGroupItem property in your Group object. What you can try is to define explicitly the Source of the binding. For example:

<telerik:RadGridView x:Name="ChildGrid" SelectedItem="{Binding SelectedGroupItem, Source={StaticResource MyViewModel}}" ...

Does this approach work for you ?  

Greetings,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 14 Feb 2013, 09:08 AM
Hello Maya
Thanks for the suggestion I saw this too in another post (http://www.telerik.com/community/forums/wpf/gridview/child-radgrid-set-selecteditem-on-viewmodel-mvvm.aspx) but I also have the same situation where the view model assigns the view's data context. 

Is there another way to do this in XAML without resorting to changing my model?

Craig
0
Craig
Top achievements
Rank 1
answered on 14 Feb 2013, 09:50 AM
This seems to successful ...

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


but when I click a column header in the root/parent grid I get a binding error as follows:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.UserControl', AncestorLevel='1''. BindingExpression:Path=DataContext.SelectedGroupItem; DataItem=null; target element is 'RadGridView' (Name='itemsGrid'); target property is 'SelectedItem' (type 'Object')


Is this to be expected? Should the binding be updated even though it is defined of a child element?
How can I avoid this?

 Craig
0
Craig
Top achievements
Rank 1
answered on 14 Feb 2013, 03:46 PM
Hi Maya
I've overcome the binding error by disabling sorting on the parent grid (CanUserSortColumns="False"). 
However, this led onto another behaviour that is stopping me progressing.

If I create this structure:

Parent1
   Child1
Parent2
   Child2

The SelectedItem binding on the child grid is only updated the first time I select (click) it i.e.
Select Child 1 - binding is updated
Select Child 2 - binding is updated
Select Child 1 - binding is NOT updated
Select Child 2 - binding is NOT updated

If I introduce a second child under Parent 1 i.e.
Parent1
   Child1
   Child3
Parent2

   Child2

then click between Child1 and Child3 the binding is updated each time. If I click Child2 the binding still does not update.
Since the child grid can still be sorted, I could click the child column header then click the child row at which time the binding is updated.

Please can you explain this behaviour and recommend how to always get a binding to update when I change the a child selection?
Thanks 
Craig

0
Maya
Telerik team
answered on 15 Feb 2013, 09:16 AM
Hi Craig,

I might be missing something, but if you select item in the first child grid (Child1), then select (Child 2) and go back to Child1 - it is still selected. That is why no selection change is invoked. Can you verify by handling SelectionChanged event and adding a break point ? Is it fired on going back to Child 1 ?
Furthermore, is the ViewModel (where SelectedGroupItem is defined) data context of the UserControl or only to the grid ? Can you try defining the binding as:

SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadGridView}},Path=DataContext.SelectedGroupItem}"

 

Regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 15 Feb 2013, 10:10 AM
Hi Maya,
The SelectionChanged event was not fired when returning to Child1. I think I understand. 
What you are saying is each child grid has to be treated independently? In that case my UI design is flawed. I want to display the selected item of the grid that has focus in a property grid alongside it. 

The child grid template is bound to a single property on the view model. 
What do I need to do to refresh the view model property with the selected item of the child grid when focus returns to it?


Regarding the binding error. If I change it to look for the RadGridView ancestor I still get a binding error i.e.
Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Telerik.Windows.Controls.RadGridView', AncestorLevel='1''. BindingExpression:Path=DataContext.SelectedGroupItem;

Craig
0
Maya
Telerik team
answered on 15 Feb 2013, 11:38 AM
Hello Graig,

As far as I can understand, you want to have only a single selected item at a time (no matter if the item is from the outer grid or the inner grids). If that is the case, I would recommend you to run through this forum thread for a reference. 

Greetings,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 15 Feb 2013, 02:14 PM
Hi Maya
Yes; I would like only a single item to be selected at a time and then for any selection change to be be notified.
I read the article and implemented the following code as advised but the behaviour remains unchanged. The selection changed event does not fire when selecting the child rows for a second time.

bool changingSelection;
 
private void GridSelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)
{
    if (changingSelection)
        return;
    changingSelection = true;
    var dataControl = e.OriginalSource as GridViewDataControl;
    var selectedItem = dataControl.SelectedItem;
 
    this.UnSelect();
    dataControl.SelectedItems.Add(selectedItem);
    changingSelection = false;
}
 
private void UnSelect()
{
    this.groupsGrid.UnselectAll();
 
    foreach (GridViewRow row in this.groupsGrid.ChildrenOfType<GridViewRow>())
    {
        if (row != null && row.IsExpanded == true)
        {
            RadGridView childGrid = row.ChildrenOfType<RadGridView>().FirstOrDefault();
            childGrid.UnselectAll();
        }
    }
}

Craig
0
Maya
Telerik team
answered on 18 Feb 2013, 09:05 AM
Hello Craig,

I have tried to reproduce the behavior you described, but without any success. Could you take a look at the sample attached and let me know what steps I need to follow in order to get the same result as the one you have?  

Kind regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 18 Feb 2013, 11:38 AM

Hi Maya,

I opened a support ticket for this last week (659698) requesting this forum post be upgraded to a support ticket. I attached a project the ticket that you can use to reproduce the problem.

I hope that is good enough.

Let me know if not.

Thanks

Craig

0
Maya
Telerik team
answered on 18 Feb 2013, 11:49 AM
Hello Craig,

I have just replied to the ticket :
"I was not able to see any binding errors on the sample attached. Even if I fill the collections - Groups and GroupItems for an item, no exceptions are thrown. Is there something else that I need to do ? Did you check the sample I sent in the forum thread ? 

All the best,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 18 Feb 2013, 12:26 PM
Hi Maya,
Change the groupsGrid RadGridView CanUserSortColumns and CanUserSortGroups to True in the XAML.

Regards
Craig
0
Craig
Top achievements
Rank 1
answered on 18 Feb 2013, 02:52 PM
Hi Maya,
I've restructured the sample you provided to be similar to mine and I have worked back through mine to determine where it is happening.

I've not specified CanUserSortColumns or CanUserSortGroups so it defaults to true and if you sort on the Club name column header you will see the binding error.

I have also found why the selected item was not set as expected. It appears to be in my view model's selected item property setter. I had if (value != null) expecting it to always execute the code when there is an object reference but it does not. When it is if (value != this.selectedPlayer) it works ok. I'm not sure why at this time. If this is a C# quirk then tell me straight; I'm still learning.
private Player selectedPlayer;
public Player SelectedPlayer
{
    get { return this.selectedPlayer; }
    set
    {
        //if (value != this.selectedPlayer)
        if (value != null)
        {
            this.selectedPlayer = value;
            this.OnPropertyChanged("SelectedPlayer");
        }
    }
}

I've attached my version of your sample to the support case (I can't add it here).
Regards
Craig
0
Maya
Telerik team
answered on 19 Feb 2013, 03:04 PM
Hi Craig,

As it turns out, I am still not able to reproduce any binding exceptions. All I did was to run the updated project you sent and sort the Name column as you said, but still without any success in getting any errors. Here is the video illustrating my attempt. Am I still missing something ?  

Greetings,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 19 Feb 2013, 03:26 PM
Hi Maya
I had removed the test data preparation from the code to make it as similar as possible to my project.

You must add some parent and child grid data at run time before clicking the parent column header.

Regards
Craig
0
Maya
Telerik team
answered on 20 Feb 2013, 12:15 PM
Hello Craig,

Indeed, I finally managed to get the exception you were describing. The thing is that when you sort, the rows will be recreated and together with its elements (like hierarchy child template, row details, etc.). And in this case with the hierarchy, it is a bit like time-issue - when the data context of the user control will be found and when the child grid and its bindings will be created.
What I could suggest is to work with the modern and more flexible way of presenting a hierarchy - RowDetails. I am attaching the updated project so that you can test the funcionality. Please let me know in case you have any further questions.  

Regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Craig
Top achievements
Rank 1
answered on 21 Feb 2013, 12:45 PM
Hello Maya,
Thanks for the update. It works fine.
Sorry for my lack of familiarity with the GridView. I was relying on the Help and Demos for guidance in representing a hierarchy.
If help and demos made mention of the use of RowDetails to represent hierarchies in the hierarchy section it may save others time.
Thanks again,
Craig
0
Dimitrina
Telerik team
answered on 21 Feb 2013, 03:06 PM
Hi Craig,

We are glad to hear your problem is now resolved.

Thank you for your feedback. I will update our documentation in the Hierarchy section to explain the different options that could be used.

Regards,
Didie
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Tags
GridView
Asked by
Craig
Top achievements
Rank 1
Answers by
Maya
Telerik team
Craig
Top achievements
Rank 1
Dimitrina
Telerik team
Share this question
or