Data binding problem with SelectedItem in child grid

19 posts, 0 answers
  1. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 13 Feb 2013 Link to this post

    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>
  2. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 14 Feb 2013 Link to this post

    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.

  3. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 14 Feb 2013 Link to this post

    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
  4. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 14 Feb 2013 Link to this post

    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
  5. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 14 Feb 2013 Link to this post

    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

  6. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 15 Feb 2013 Link to this post

    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.

  7. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 15 Feb 2013 Link to this post

    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
  8. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 15 Feb 2013 Link to this post

    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.

  9. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 15 Feb 2013 Link to this post

    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
  10. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 18 Feb 2013 Link to this post

    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.

  11. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 18 Feb 2013 Link to this post

    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

  12. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 18 Feb 2013 Link to this post

    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.

  13. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 18 Feb 2013 Link to this post

    Hi Maya,
    Change the groupsGrid RadGridView CanUserSortColumns and CanUserSortGroups to True in the XAML.

    Regards
    Craig
  14. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 18 Feb 2013 Link to this post

    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
  15. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 19 Feb 2013 Link to this post

    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.

  16. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 19 Feb 2013 Link to this post

    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
  17. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 20 Feb 2013 Link to this post

    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.

  18. Craig
    Craig avatar
    113 posts
    Member since:
    Nov 2011

    Posted 21 Feb 2013 Link to this post

    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
  19. Dimitrina
    Admin
    Dimitrina avatar
    3769 posts

    Posted 21 Feb 2013 Link to this post

    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.

Back to Top