Wednesday 10 December 2014


Share/Bookmark

Introduction

In telerik WPF radgridview, when we apply grouping, we can find that some groups will automatically expand even if there is no user interaction. This mostly happens in scenario when there is some value change in rows which are grouped. This will also happen in other scenarios as well. This is a known bug in telerik radgridview at the time when this post is posted.
In this post you will find out how to block this bug with the help of a custom behavior. Here we will make use of mouse click event and GroupRowIsExpandedChanging events. Here subscribing to mouse click events may look tricky; in order to understand this, you have to refer to this post.


How to fix this?

Here we will create a behavior which can be applied to a radgridview. We can apply the same code in code behind as well but we will stick to MVVM model in this post. Here we will subscribe to mouse click event and find out the row which is clicked and we will allow only Expand/Collapse of those group and we will cancel all Expand/Collapse events on other rows. In this way we can avoid other rows getting expanded or collapsed when there is some Expand/Collapse event which got triggered automatically. Below given is the full code of the custom behavior which we need to use.

 using System.ComponentModel;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using Telerik.Windows.Controls;
    using Telerik.Windows.Controls.GridView;

    public class RadGridViewGroupingBugBehavior : Behavior<RadGridView>
    {
        private int clicks = 0;
        private bool notInitialized = true;

        private object lockObject = new object();

        private MouseButtonEventHandler mouseButtonEventHandler;

        public RadGridViewGroupingBugBehavior()
        {
            this.mouseButtonEventHandler = this.GridViewRowMouseLeftButtonDown;
        }

        private GridViewGroupRow GroupingRow { get; set; }

        protected override void OnAttached()
        {
            base.OnAttached();

            this.AssociatedObject.DataLoaded += AssociatedObjectDataLoaded;
            this.AssociatedObject.PropertyChanged += AssociatedObjectPropertyChanged;
            this.AssociatedObject.RowLoaded += AssociatedObjectRowLoaded;
            this.AssociatedObject.GroupRowIsExpandedChanging += AssociatedObjectGroupRowIsExpandedChanging;
        }
        
        private void AssociatedObjectDataLoaded(object sender, System.EventArgs e)
        {
            notInitialized = true;
        }
        
        private void AssociatedObjectPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            notInitialized = true;
        }
        
        private void AssociatedObjectGroupRowIsExpandedChanging(object sender, GroupRowCancelEventArgs e)
        {
            lock (lockObject)
            {
                IGroupRow groupRow = e.Row;
                if (((GroupingRow == groupRow) && (clicks > 0)) || notInitialized)
                {
                    notInitialized = false;
                    clicks = 0;
                    GroupingRow = null;
                }
                else
                {
                    e.Cancel = true;
                    e.Handled = true;
                }    
            }
        }

        private void AssociatedObjectRowLoaded(object sender, RowLoadedEventArgs e)
        {
            var row = e.Row as GridViewRow;
            if (row != null)
            {
                /*This is to make sure that we dont subscribe again*/
                AssociatedObject.RemoveHandler(GridViewRow.MouseLeftButtonDownEvent, mouseButtonEventHandler);
                AssociatedObject.AddHandler(GridViewRow.MouseLeftButtonDownEvent, mouseButtonEventHandler, true);
            }
        }

        private void GridViewRowMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.AssociatedObject.IsGrouping)
            {
                var senderElement = e.OriginalSource as FrameworkElement;
                var parentRow = senderElement.ParentOfType<GridViewRow>();
                
                var parentGroupRow = senderElement.ParentOfType<GridViewGroupRow>();

                if (parentGroupRow != null)
                {
                    GroupingRow = parentGroupRow;
                    clicks++;
                }
            }
        }
    }
From your XAMl side, you have to add this behavior like as shown below.
<telerik:RadGridView 
AreRowDetailsFrozen="True"
AutoGenerateColumns="False"
IsFilteringAllowed="True"
IsReadOnly="True"
ItemsSource="{Binding ItemsList}"
RowIndicatorVisibility="Collapsed"
SelectionMode="Extended" >
 <telerik:RadGridView.GroupDescriptors>
  <telerik:GroupDescriptor Member="NodeId" />
 </telerik:RadGridView.GroupDescriptors>

[…rest of the code here…]

  </telerik:RadGridView.Columns>
    <i:Interaction.Behaviors>
      <behaviors:RadGridViewGroupingBugBehavior />
    </i:Interaction.Behaviors>
 </telerik:RadGridView>
Categories:

2 comments:

  1. Thanks for you sharing, that's great.
    But if i set row virtualization is true for big datasource.
    The issue of group is still there, group is automatical expand.
    Please review this case and help me.
    Thanks a lot.

    ReplyDelete
  2. I tried this out and it was working fine. Can i have a look at the code snippet?
    Just how you use this behavior.

    ReplyDelete

Dear reader, Your comment is always appreciated. I will reply to your queries as soon as possible.

1. Make sure to click on the Subscribe By Email link to be notified of follow up comments and replies. Or you can use Subscribe to: Post Comments (Atom) link.
2. Only English comments shall be approved.
3. Please make your comments self-explanatory. Comment in such a way that it explains the comment so that a counter question can be avoided and can be replied with proper answer on the first go.