This is a migrated thread and some comments may be shown as answers.
Getting selected row of a child grid
5 Answers 60 Views
This is a migrated thread and some comments may be shown as answers.
Adrian
Top achievements
Rank 1
Adrian asked on 06 Jun 2014, 06:29 AM
I am having some issues getting the row that is selected in any child grid.

My main grid is a grid of Manufacturers and each row can be expanded to view each manufacturer's parts. This is no problem. The problem is getting the current row with in each expanded child grid. Here is my code so far.

public partial class ManufacturersAndPartsSearch : Window
   {
       private ViewModels.ManufacturersAndPartsSearchViewModel vm;
       public ManufacturersAndPartsSearch()
       {
           InitializeComponent();
           var context = new ViewModels.ManufacturersAndPartsSearchViewModel(this);
           this.vm = context;
           this.DataContext = vm;
 
           GridViewTableDefinition d = new GridViewTableDefinition();
           d.Relation = new Telerik.Windows.Data.PropertyRelation("ChildParts");
 
           //add child table defination to gridview
           this.GridView.ChildTableDefinitions.Add(d);
            
 
           this.GridView.DataLoaded += GridView_DataLoaded;
 
           //this is to alter changes to each child grid
           this.GridView.DataLoading += GridView_DataLoading;
 
           //event to check and set the view model's current row to a heirarchial's currently selected row if selected
 
           //explanation
           /*The original code used data binding to set the current row in the viewmodel equal to the current row in the grid
            this worked for the original purpose; however, since heirarchial grids are created for each row in the parent grid
            that has parts saved in the database then there is no way to bind their currently selected row properties to the viewmodel
             
            The databinding was ditched and instead this route was taken which accounts for both types of grids*/
           this.GridView.SelectionChanged += GridView_SelectionChanged;
       }
 
       void GridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
       {
           var grid = sender as RadGridView;
           var item = grid.SelectedItem;
           this.vm.CurrentItem = item;
           MessageBox.Show(item.GetType().ToString());
       }

When my message box shows I always get a type of "PartsManufacturerViewModel". This would be correct in the parent grid because I am binding to my viewmodel's "ManufacturersAndPartsSearchViewModel.CurrentItem which is of type object. Since I am binding the grid to a collection of PartsManufacturerViewModels then this is expected. When I click on a child row I still get the same type but I should be getting PartViewModel, which is a property inside of PartsManufacturerViewModel. 

The basic gist is this. PartsManufacturerViewModel holds data relevant to the manufacturer while it has a property called "ChildParts" which is a collection of PartViewModels (which hold data relevant to the part itself). It is this collection that I bind the ChildTableDefinitions to. 

My desired outcome is to be able to set "this.vm.CurrentItem" to either a PartsManufacturerViewModel or a PartViewModel depending on the current row that is clicked once, either in the parent or the child grid.



Here is the rest of my code (ViewModels) if it helps make things clearer.

public class PartsManufacturerViewModel : Accu_Base_Lib.Bases.ModelViewModelBase<DAL.PartsManufacturer>
   {
 
 
       public string Id
       {
           get { return (string)GetValue(IdProperty); }
           set { SetValue(IdProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for Id.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty IdProperty =
           DependencyProperty.Register("Id", typeof(string), typeof(PartsManufacturerViewModel));
 
 
 
 
       public string Name
       {
           get { return (string)GetValue(NameProperty); }
           set { Debug.WriteLine("ViewModel Name Changed " + this.Name); SetValue(NameProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty NameProperty =
           DependencyProperty.Register("Name", typeof(string), typeof(PartsManufacturerViewModel));
 
       private ObservableCollection<PartViewModel> _childParts;
 
       public ObservableCollection<PartViewModel> ChildParts
       {
           get
           {
               if (this._childParts == null)
               {
                   GetChildren();
               }
 
               return this._childParts;
           }
 
           set
           {
               this._childParts = value;
           }
       }
 
        
       public PartsManufacturerViewModel(DAL.PartsManufacturer model)
            
       {
           base.Init(model);
           //Fills this viewmodel based off the model supplied.
           UpdateViewModelFromModel();
       }
 
       public PartsManufacturerViewModel()
       {
           base.Init();
           this.Model.Id = Guid.NewGuid().ToString();
           this.Model.Name = string.Empty;
           UpdateViewModelFromModel();
       }





public class PartViewModel : Accu_Base_Lib.Bases.ModelViewModelBase<DAL.Part>
   {
 
 
       public string Id
       {
           get { return (string)GetValue(IdProperty); }
           set { SetValue(IdProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for Id.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty IdProperty =
           DependencyProperty.Register("Id", typeof(string), typeof(PartViewModel));
 
 
 
 
       public string ManufacturerId
       {
           get { return (string)GetValue(ManufacturerIdProperty); }
           set { SetValue(ManufacturerIdProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for ManufacturerId.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty ManufacturerIdProperty =
           DependencyProperty.Register("ManufacturerId", typeof(string), typeof(PartViewModel));
 
 
 
 
       public string Name
       {
           get { return (string)GetValue(NameProperty); }
           set { SetValue(NameProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for Name.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty NameProperty =
           DependencyProperty.Register("Name", typeof(string), typeof(PartViewModel));
 
 
 
 
       public string ModelNo
       {
           get { return (string)GetValue(ModelNoProperty); }
           set { SetValue(ModelNoProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for ModelNo.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty ModelNoProperty =
           DependencyProperty.Register("ModelNo", typeof(string), typeof(PartViewModel));
 
 
 
 
 
 
 
 
       public decimal Price
       {
           get { return (decimal)GetValue(PriceProperty); }
           set {
               SetValue(PriceProperty, value); }
       }
 
       // Using a DependencyProperty as the backing store for Price.  This enables animation, styling, binding, etc...
       public static readonly DependencyProperty PriceProperty =
           DependencyProperty.Register("Price", typeof(decimal), typeof(PartViewModel));
 
        
 
        
 
        
 
 
       public PartViewModel(DAL.Part model)
            
       {
           base.Init(model);
           //Fills this viewmodel based off the model supplied.
           UpdateViewModelFromModel();
       }
 
       public PartViewModel()
       {
           base.Init();
           this.Model.Id = Guid.NewGuid().ToString();
           UpdateViewModelFromModel();
       }



5 Answers, 1 is accepted

Sort by
0
Adrian
Top achievements
Rank 1
answered on 06 Jun 2014, 06:35 AM
And the reason I am trying to do this is to validate which buttons should be enabled or disabled using commands.
This is the CanExecute method that enables/disables a button that allows for a new part to be added to the database. This can only happen if a Manufacturer is selected. If a part is selected then the button should be disabled.
public override bool CanExecute(object parameter)
        {
            if (this.vm.CurrentItem == null)
                return false;
            else if (this.vm.CurrentItem.GetType() != typeof(ViewModels.PartsManufacturerViewModel))
                return false;
            else
                return true;
        }
0
Accepted
Dimitrina
Telerik team
answered on 06 Jun 2014, 08:42 AM
Hi,

You can bind the SelectedItem of your GridViews to this.vm.CurrentItem.
That way the value in the ViewModel will be updated as soon as the user selects an item.

Regards,
Didie
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
0
Adrian
Top achievements
Rank 1
answered on 06 Jun 2014, 02:55 PM
How would I bind to it from each child grid?

<telerik:RadGridView Name="GridView"
                             Grid.Row="1"
                             CanUserDeleteRows="False"
                             CanUserFreezeColumns="False"
                             CanUserInsertRows="False"
                             CanUserResizeColumns="True"
                             CanUserReorderColumns="True"
                             CanUserResizeRows="True"
                             CanUserSortColumns="True"
                             CanUserSortGroups="True"
                             SelectionMode="Single"
                             EnableRowVirtualization="True"
                             EnableColumnVirtualization="True"
                             FilteringMode="FilterRow"
                             ItemsSource="{Binding DataContext}"
                             SelectedItem="{Binding CurrentItem}"
                             IsReadOnly="True"
                             >
            <telerik:RadGridView.ChildTableDefinitions>
                <telerik:GridViewTableDefinition>
                </telerik:GridViewTableDefinition>
            </telerik:RadGridView.ChildTableDefinitions>
            <telerik:RadGridView.HierarchyChildTemplate>
                <DataTemplate>
                    <telerik:RadGridView ItemsSource="{Binding ChildParts}"
                                         SelectedItem="{Binding CurrentItem}"/>
                </DataTemplate>
            </telerik:RadGridView.HierarchyChildTemplate>
        </telerik:RadGridView>
0
Adrian
Top achievements
Rank 1
answered on 06 Jun 2014, 03:25 PM
WPF binding confuses me sometimes :p

I got it to work using a relative source.

<telerik:RadGridView ItemsSource="{Binding ChildParts}"
                                         SelectedItem="{Binding Path=DataContext.CurrentItem, Mode=OneWayToSource
                        , RelativeSource={RelativeSource AncestorType={x:Type telerik:RadGridView}}}"/>
0
Dimitrina
Telerik team
answered on 09 Jun 2014, 09:05 AM
Hello,

Having in mind RadGridView is a virtualized control, it is not recommended to work with the RelativeSource as the Name scope is not reliable.

In order to get the Binding still be resolved in your case, you could specify a valid Source for it. You can define the ViewModels.ManufacturersAndPartsSearchViewModel as a StaticResource and then set it as a Source for the binding.

Regards,
Didie
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Asked by
Adrian
Top achievements
Rank 1
Answers by
Adrian
Top achievements
Rank 1
Dimitrina
Telerik team
Share this question
or