Binding RadGridView's SelectedItem(s) and SelectedCells (MVVM) using a RadContextMenu

14 posts, 0 answers
  1. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 01 Nov Link to this post

    Hi,

    We are currently using Telerik's RadGridView control with extended/mixed mode selection enabled.

    Is there any way to Bind directly to the:

    a) SelectedItem/SelectedItems

    b) The SelectedCells' Column and Item(s) properties

    c) FilterDescriptors (to suspend/resume notifications)

    Using a RadContextMenu for Pure MVVM?

    We are currently using an approach with references RadGridView UI elements via the ViewModel, which we'd like to avoid. We have also considered the SelectedItems approach through a behavior, as illustrated here:

    http://www.telerik.com/blogs/how-to-synchronize-your-ui-selected-items-with-your-data-context-using-mvvm-and-blend-behaviors-for-silverlight-and-wpf

    However, the performance of the selection slows the larger the number of items highlighted, since the behavior is triggering the Transfer method in the behavior for each row highlighted in the RadGridView. We'd like to avoid using a behavior, if possible, as our users are working with large datasets and will need to be able to selected 1M+ rows at a time.

    Currently, we are using this approach, where we are able to pass the RadGridView to the ViewModel as a CommandParameter from a RadContextMenu in its entirety:

    <telerik:RadGridView Grid.Row="1" 
                                 Name="dtgMyData" 
                                 ItemsSource="{Binding Path=MyDataCollection}" 
                                 AutoGenerateColumns="False" 
                                 IsReadOnly="False" 
                                 RowIndicatorVisibility="Visible"
                                 HorizontalAlignment="Stretch"
                                 SelectionMode="Extended"
                                 SelectionUnit="Mixed">

    ...

    <telerik:RadContextMenu.ContextMenu>
                    <telerik:RadContextMenu x:Name="MyDataGridContextMenu">
                        <telerik:RadContextMenu.Items>
                            <telerik:RadMenuItem Header="Filter Selected" Command="{Binding DataContext.FilterSelectionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadContextMenu}}}" CommandParameter="{Binding Path=UIElement, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:RadContextMenu}}"/>
                    </telerik:RadContextMenu>
                </telerik:RadContextMenu.ContextMenu>

    ...

    ...<columns>...

    Where the Command and CommandParameters are bound to the ViewModel.

    Is there a way to avoid binding to the ViewModel directly referencing UI controls using a RadContextMenu without using behaviors? For example, is there another Binding option for the CommandParameter above that is shown to reference the entire RadGridView, such that we can reference SelectedCells.Item(s) or SelectedItem/SelectedItems bound to our Model (i.e. MyData) directly, and if at all possible, the Column and/or Column FilterDescriptors without having to use code-behind and avoiding the use of a behavior?

     

    Kind regards

     

  2. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 04 Nov Link to this post

    Hello Abhinav,

    Thank you for the detailed description of your requirement.

    The SelectedItems, SelectedCells and FilterDescriptors collections exposed by RadGridView are not dependency properties, thus binding directly to them is not possible. I am afraid, that we are not planning to modify this default design of the control. With this in mind, implementing an attached behavior as demonstrated in the blog post to which you referred would be the appropriate approach for this requirement. You can also take a look at the Binding SelectedItems from ViewModel SDK example for further reference. It can be reviewed through the SDK Browser.

    Hopefully, this clarifies your concerns.

    Regards,
    Stefan X1
    Telerik by Progress
    Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
  3. UI for WPF is Visual Studio 2017 Ready
  4. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 04 Nov in reply to Stefan X1 Link to this post

    Hi Stefan X1,

    Thanks very much for responding.

    We have attempted the behavior referred in the SDK, however this solution is not feasible for our requirements due to the transferring of a large number of items to a bound collection in the ViewModel (1M+).

  5. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 07 Nov in reply to Abhinav Link to this post

    Hi Stefan X1,

    Thanks very much for your help. Would it be possible to bind the SelectedCells to an IValueConverter? We'd like to benchmark the performance of a Converter compared to the behavior, if possible.

    For example, we'd like to attempt to bind SelectedCells using the SelectedCellsChanged EventTrigger and pass to the ViewModel the SelectedCells' Items and/or Columns.

    Kind regards

  6. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 08 Nov Link to this post

    Hello Abhinav,

    The IValueConverter is meant to be applied to a Binding itself. Since the SelectedCells property is not a dependency one, I am not sure to which binding will the converter be applied. Can you please shed some light on this? Also, what conversion would the IValueConverter perform?

    Thanks in advance for your cooperation. I will be looking forward to your reply.

    Regards,
    Stefan X1
    Telerik by Progress
    Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
  7. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 08 Nov in reply to Stefan X1 Link to this post

    Hi Stefan X1,

    Thanks again for your quick reply.

    We currently using reflection to get the SelectedCells so that we can apply custom filters programmatically through a ContextMenu click event on the RadGridView which filters the grid based on the cells the user had selected, however, we were hoping to change this code-behind 'click event' to a ViewModel 'command', without directly referencing the UI elements in the ViewModel. We are able to bind SelectedItems, which exposes the underlying model, to a command in the ViewModel using an EventTrigger and we were hoping to do this with SelectedCells, as well. It seems SelectedCells is wrapped by an internal type, so we are not able to expose the properties without using reflection.  We were hoping to return a user object from a custom IValueConverter, returning the Columns and the Items of the SelectedCells, as does the SelectedItems.

     

    Kind regards

  8. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 11 Nov Link to this post

    Hello Abhinav,

    Thanks for this clarification.

    The SelectedCells collection of RadGridView is of type GridViewCellInfo, which exposes the Column and Item properties. Generally, they should be enough for implementing the filtering you need. Can you please share some details on which are the properties you need and you are trying to access through reflection?

    As to reacting to a UI event in the view model, you can benefit from the EventToCommandBehavior that we provide. Can you please check it out and let me know whether it corresponds to your needs?

    Regards,
    Stefan X1
    Telerik by Progress
    Do you need help with upgrading your WPF project? Try the Telerik API Analyzer and share your thoughts!
  9. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 14 Nov in reply to Stefan X1 Link to this post

    Hi Stefan X1,

    Thanks again for your input.

    The EventToCommandBehavior still requires passing a UI element to the ViewModel.

    We're attempting to use an IValueConverter using a custom object to convert from the GridViewCellInfo object. Using this converter, we are internally transposing the GridViewCellInfo object into a custom container object that we created to use as the Model, i.e. a

    [ValueConversion(typeof(IList<GridViewCellInfo>), typeof(SelectedCellsContainer))]

    The converter would have worked except for the fact that the Command is triggering first, then the converter. Here is an example of our usage in XAML:

    <RadGridView>

    ...

                    <i:EventTrigger EventName="SelectedCellsChanged">
                        <i:InvokeCommandAction Command="{Binding SelectionCellsChangedCommand }"  CommandParameter="{Binding ElementName=dtgMyDataGrid, Path=SelectedCells }"  />
                        CommandParameter="{Binding ElementName=dtgFills,Converter={StaticResource SelectedCellConverter},Path=SelectedCells }"
                    </i:EventTrigger>
    ...

    </RadGridView>

    Could you please shed some light as to why the Command is triggering before the Converter? Do we need to bind the CommandParameter to an ancestor for the InvokeCommandAction, as in:

    CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridCell}},Converter={StaticResource DataGridCellToRowActionParametersConverter}}">

    I hope this explains things clearly.

    Kind regards.
  10. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 14 Nov in reply to Abhinav Link to this post

    Hi,

    Correction on the EventTrigger XAML from above:

                    <i:EventTrigger EventName="SelectedCellsChanged">
                        <i:InvokeCommandAction Command="{Binding SelectionCellsChangedCommand }"  CommandParameter="{Binding ElementName=dtgMyDataGrid, Path=SelectedCells }"  />
                        CommandParameter="{Binding ElementName=dtgMyDataGrid,Converter={StaticResource SelectedCellConverter},Path=SelectedCells }"
                    </i:EventTrigger>

     

    Kind regards

  11. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 17 Nov Link to this post

    Hi Abhinav,

    Thanks for the clarification.

    I made a research on the reported behavior and found out the following StackOverflow threads.

    - How to convert command parameter just before command is executed?
    - WPF CommandParameter is NULL first time CanExecute is called

    Can you please check them out? Are the solutions demonstrated in them corresponding to your scenario?

    Best Regards,
    Stefan X1
    Telerik by Progress
    Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
  12. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 17 Nov in reply to Stefan X1 Link to this post

    Hi Stefan X1,

    Thanks again for your support.

    I've seen the first link, however, how do we get the data context of the RadGridView from a ContextMenu using MVVM? The command will not trigger unless it's bound to RadContextMenu.

    I will take a look at the second option, as well.

  13. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 22 Nov Link to this post

    Hello Abhinav,

    Can you please share some details on whether you managed to test the implementation with a RelativeSource binding, as demonstrated in the second thread to which I referred? If it does not help, I suggest you sticking to the approach of implementing an attached behavior, as mentioned in one of my previous replies.

    Best Regards,
    Stefan X1
    Telerik by Progress
    Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
  14. Abhinav
    Abhinav avatar
    17 posts
    Member since:
    Jun 2016

    Posted 23 Nov in reply to Stefan X1 Link to this post

    Hi Stefan X1,

    We've managed to develop an approach to capture the Grid's CellInfoCollection from a Command in our ContextMenuItem, by way of:

    <telerik:RadMenuItem Header="Filter Selected" Command="{Binding DataContext.FilterSelectionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadContextMenu}}}" CommandParameter="{Binding Path=UIElement.SelectedCells, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:RadContextMenu}}"/>

    Here, we are passing SelectedCells to the VM and converting the cells to a custom model in the VM. We will go with this approach for now.

    We've benchmarked the attached behavior approach and have found it to not be responsive enough for our user's needs.

     

    Thanks very much for your help.

     

    Kind regards.

  15. Stefan X1
    Admin
    Stefan X1 avatar
    523 posts

    Posted 24 Nov Link to this post

    Hello Abhinav,

    I am happy that you have managed to find a solution that meets your requirements.

    In case you need any other assistance with our components, do not hesitate to contact us again.

    All the best,
    Stefan X1
    Telerik by Progress
    Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
Back to Top
UI for WPF is Visual Studio 2017 Ready