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

[Solved] Vertical Scroll in Child Grid Not Working

12 Answers 538 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Devin Losee
Top achievements
Rank 1
Devin Losee asked on 22 Feb 2010, 04:20 PM

I found a couple of possible issues with the RowDetailsTemplate for the RadGridView.  If the main grid resides in a ScrollViewer, scrolling does not appear to work correctly for the child grid.  I created a bare-bones sample that can easily reproduce the issues (issues listed below).  This sample just uses one page so you can just copy & paste the XAML & code behind to get it working.  For other reasons, we need to use the RowDetailsTemplate (not ChildTableDefinitions) and also we need the parent grid encapsulated into a ScrollViewer (not scroll the parent grid).  If you could let me know if there is anything I am doing wrong or if there is any work-around, it would be greatly appreciated.  Thanks.

  1. Child grid vertical scroll does not actually scroll
  2. Margins/Padding do not appear to be taken into account when doing HorizontalAlignment=”Stretch” (you will notice that when the row expands, the parent grid is stretched horizontally – you see what looks to be an extra blank column)

 


XAML

 

<UserControl x:Class="TestTelerikGrid.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:telerikGridView="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView" 
    mc:Ignorable="d" 
    Width="Auto" Height="Auto">  
 
    <Grid x:Name="LayoutRoot">  
        <ScrollViewer VerticalScrollBarVisibility="Visible">  
            <telerikGridView:RadGridView x:Name="ParentGrid" 
                                         ItemsSource="{Binding ViewModelDetails, Mode=TwoWay}"   
                                         SelectedItem="{Binding ViewModelDetail, Mode=TwoWay}" 
                                         RowDetailsVisibilityMode="VisibleWhenSelected" 
                                         IsReadOnly="True" 
                                         ScrollViewer.HorizontalScrollBarVisibility="Visible" 
                                         ScrollViewer.VerticalScrollBarVisibility="Visible" 
                                         AutoGenerateColumns="False" 
                                         ColumnsWidthMode="Fill" 
                                         CanUserFreezeColumns="False" 
                                         GridLinesVisibility="None" 
                                         CanUserReorderColumns="False" 
                                         CanUserInsertRows="False" 
                                         CanUserResizeColumns="True" 
                                         ShowGroupPanel="True" 
                                         UseAlternateRowStyle="True" 
                                         RowIndicatorVisibility="Collapsed" 
                                         Width="Auto" 
                                         SelectionChanged="ParentGrid_SelectionChanged" 
                                         > 
                <telerikGridView:RadGridView.RowDetailsTemplate> 
                    <DataTemplate> 
                        <telerikGridView:RadGridView x:Name="DetailGrid" 
                                                     ItemsSource="{Binding GridItemsDetail, Mode=TwoWay}" 
                                                     SelectedItem="{Binding GridSelectedItemDetail, Mode=TwoWay}" 
                                                     IsReadOnly="True" 
                                                     AutoGenerateColumns="False" 
                                                     CanUserFreezeColumns="False" 
                                                     VerticalGridlinesVisibility="Collapsed" 
                                                     GridLinesVisibility="Horizontal" 
                                                     CanUserReorderColumns="False" 
                                                     CanUserInsertRows="False" 
                                                     ShowGroupPanel="True" 
                                                     UseAlternateRowStyle="True" 
                                                     RowIndicatorVisibility="Collapsed" 
                                                     AutoExpandGroups="True" 
                                                     Margin="5" 
                                                     ScrollViewer.HorizontalScrollBarVisibility="Auto" 
                                                     ScrollViewer.VerticalScrollBarVisibility="Visible" 
                                                     ColumnsWidthMode="Fill" 
                                                     ScrollMode="Deferred" 
                                                     DataLoadMode="Asynchronous" 
                                                     MaxHeight="350" 
                                                     VirtualizingStackPanel.VirtualizationMode="Recycling">  
                            <telerikGridView:RadGridView.Columns> 
                                <telerikGridView:GridViewDataColumn Header="ID" UniqueName="ID" TextWrapping="Wrap" Width="100"/>  
                                <telerikGridView:GridViewDataColumn Header="Name" UniqueName="Name" TextWrapping="Wrap"/>  
                            </telerikGridView:RadGridView.Columns> 
                        </telerikGridView:RadGridView> 
                    </DataTemplate> 
                </telerikGridView:RadGridView.RowDetailsTemplate> 
 
                <telerikGridView:RadGridView.Columns> 
                    <telerikGridView:GridViewDataColumn Header="ID" UniqueName="ID" TextWrapping="Wrap" Width="100"/>  
                    <telerikGridView:GridViewDataColumn Header="Name" UniqueName="Name" TextWrapping="Wrap"/>  
                </telerikGridView:RadGridView.Columns> 
            </telerikGridView:RadGridView> 
        </ScrollViewer> 
    </Grid> 
</UserControl> 

 

 

Code Behind

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Net;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Animation;  
using System.Windows.Shapes;  
using System.ComponentModel;  
using System.Collections.ObjectModel;  
using Telerik.Windows.Controls;  
 
namespace TestTelerikGrid  
{  
    public partial class MainPage : UserControl, INotifyPropertyChanged  
    {  
        public MainPageViewModel m_viewModel;  
 
        public MainPage()  
        {  
            InitializeComponent();  
 
            m_viewModel = new MainPageViewModel();  
            this.DataContext = m_viewModel;  
 
            ObservableCollection<MainPageDetailViewModel> items = new ObservableCollection<MainPageDetailViewModel>();  
            for (int counter = 1; counter <= 10; counter++)  
            {  
                items.Add(new MainPageDetailViewModel() { ID = counterName = "Test Items " + counter.ToString() });  
            }  
            m_viewModel.ViewModelDetails = items;  
        }  
 
        private void ParentGrid_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)  
        {  
            if (e.AddedItems != null && e.AddedItems.Count > 0)  
            {  
                MainPageDetailViewModel model = e.AddedItems[0] as MainPageDetailViewModel;  
                if (model == null) { return; }  
 
                ObservableCollection<TestItemDetail> items = new ObservableCollection<TestItemDetail>();  
                for (int counter = 1; counter <= 100; counter++)  
                {  
                    items.Add(new TestItemDetail() { HeaderId = model.ID, ID = counterName = "Test Items " + counter.ToString() });  
                }  
                model.GridItemsDetail = items;  
            }  
        }  
 
        #region INotifyPropertyChanged Members  
 
        public event PropertyChangedEventHandler PropertyChanged;  
 
        protected virtual void RaisePropertyChanged(string propertyName)  
        {  
            if (this.PropertyChanged != null)  
            {  
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
            }  
        }  
 
        #endregion  
    }  
 
    public class TestItemDetail  
    {  
        public int HeaderId { get; set; }  
        public int ID { get; set; }  
        public string Name { get; set; }  
    }  
 
    public class MainPageViewModel : INotifyPropertyChanged  
    {  
        private MainPageDetailViewModel m_viewModelDetail;  
        private ObservableCollection<MainPageDetailViewModel> m_viewModelDetails;  
 
        public ObservableCollection<MainPageDetailViewModel> ViewModelDetails  
        {  
            get { return m_viewModelDetails; }  
            set  
            {  
                m_viewModelDetails = value;  
                RaisePropertyChanged("ViewModelDetails");  
            }  
        }  
 
        public MainPageDetailViewModel ViewModelDetail  
        {  
            get { return m_viewModelDetail; }  
            set  
            {  
                m_viewModelDetail = value;  
                RaisePropertyChanged("ViewModelDetail");  
            }  
        }  
 
        #region INotifyPropertyChanged Members  
 
        public event PropertyChangedEventHandler PropertyChanged;  
 
        protected virtual void RaisePropertyChanged(string propertyName)  
        {  
            if (this.PropertyChanged != null)  
            {  
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
            }  
        }  
 
        #endregion  
    }  
 
    public class MainPageDetailViewModel : INotifyPropertyChanged  
    {  
        private TestItemDetail m_gridSelectedItemDetail;  
        private ObservableCollection<TestItemDetail> m_gridItemsDetail;  
 
        public TestItemDetail GridSelectedItemDetail  
        {  
            get { return m_gridSelectedItemDetail; }  
            set  
            {  
                m_gridSelectedItemDetail = value;  
                RaisePropertyChanged("GridSelectedItemDetail");  
            }  
        }  
 
        public ObservableCollection<TestItemDetail> GridItemsDetail  
        {  
            get { return m_gridItemsDetail; }  
            set  
            {  
                m_gridItemsDetail = value;  
                RaisePropertyChanged("GridItemsDetail");  
            }  
        }  
 
        public int ID { get; set; }  
        public string Name { get; set; }  
 
        #region INotifyPropertyChanged Members  
 
        public event PropertyChangedEventHandler PropertyChanged;  
 
        protected virtual void RaisePropertyChanged(string propertyName)  
        {  
            if (this.PropertyChanged != null)  
            {  
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
            }  
        }  
 
        #endregion  
    }  

 

12 Answers, 1 is accepted

Sort by
0
Devin Losee
Top achievements
Rank 1
answered on 22 Feb 2010, 06:30 PM
I also noted that if I specifically set the width of the child grid, this no longer happens.  For example if I add the event handler below on the Loaded event of the child grid, it appears to be working fine.  Too bad we cannot set an explicit width and we need that HorizontalAlignment set to "stretch".

private void DetailGrid_Loaded(object sender, RoutedEventArgs e)  
{  
    double w = ((RadGridView)sender).ActualWidth;  
    ((RadGridView)sender).HorizontalAlignment = HorizontalAlignment.Left;  
    ((RadGridView)sender).Width = w;  
0
Rossen Hristov
Telerik team
answered on 23 Feb 2010, 07:59 AM
Hi Devin Losee,

Placing RadGridView inside a ScrollViewer is not a good idea. If you want to have normal scrolling you cannot place RadGridView in containers that are measured with infinity. And one such container is the ScrollViewer. As you noticed yourself specifying an explicit width fixes things up. This is not an issue of RadGridView. This is just how the measuring and layout system works in Silverlight. When an element is given infinite space to render it uses all the space it needs. So you will have to specify some specific size constraints for both your parent and child grid if you want their scrolling to behave normally. And place the top-level grid in something other than ScrollViewer. You can let RadGridView do the scrolling for you -- it has its own set of scrollbars.

I hope this helps. Let us know if you have any other questions.

Kind regards,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Devin Losee
Top achievements
Rank 1
answered on 23 Feb 2010, 02:02 PM
The odd thing is that a regular silverlight grid works fine in this scenario.  It is only the RadGridView that is causing the scrolling issue.  We really want to keep the functionality of the RadGridView as the child grid, and due to the layout of the application, we need that outer scroll viewer and cannot just use scrolling in the parent grid (the parent grid is located on a page with a number of other controls which is why the outer scroll viewer is required).  There has to be some sort of work-around for this (possibly updating the layout based on a grid event or something) to force the child scrollbar and width to correct itself.  Again, any help or possible work-arounds would be appreciated.  Thanks.
0
Rossen Hristov
Telerik team
answered on 23 Feb 2010, 02:29 PM
Hi Devin Losee,

Aren't those issues resolved when you specify explicit sizes for both the parent and row details grid? Please, try setting some width and height on either the grid or somewhere up the tree of its ancestors. Then you can keep the outer scroll viewer.

Best wishes,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Devin Losee
Top achievements
Rank 1
answered on 23 Feb 2010, 02:39 PM
Yes that will work.  We were just hoping to keep the width stretching the width of the screen so it does not look small on large screens or does not force a scroll on smaller ones.
0
Rossen Hristov
Telerik team
answered on 23 Feb 2010, 02:46 PM
Hi Devin Losee,

Another thing that affects this behavior is horizontal (column) virtualization. When it is turned on and the grid is measured with infinity in the horizontal direction, unexpected results may occur.

You can try turning it off instead of using the fixed sizes approach. Remember, that the MS DataGrid does not have column virtualization. Maybe this is making the difference. You can try turning it off by setting the EnableColumnVirtualization property. I hope this helps.

Best wishes,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Devin Losee
Top achievements
Rank 1
answered on 23 Feb 2010, 03:02 PM
I tried setting that property with no luck.  Another odd thing is that it appears to initially draw correctly, and just before it is done loading, you see the width increase past the screen.  Do you know of any event that may be getting fired causing this?
0
Devin Losee
Top achievements
Rank 1
answered on 23 Feb 2010, 08:52 PM
Through a complete hack, we have the functionality we are looking for.  I still think since the regular silverlight grid renders properly, it has to be something in the RadGridView that is causing the scrolling problem.  I'll list out the basic steps of the hack below for anyone that is interested, but I would still like to see a fix, better solution, or even a better work-around if possible.

  1. Hook into the SizeChanged event in the parent grid
    1. In this event handler, raise an event that passes the SizeChangedEventArgs
  2. Hook into the Loaded event in the child grid
    1. In this event handler, do the following
      1. Set a local variable to the RadGridView (the sender) to be used later
      2. Store the ActualWidth property of the grid locally
      3. Set the HorizontalAlignment of the grid to Left
      4. Set the Width of the grid to the ActualWidth of the grid (from variable in step 2)
      5. Note: you may not need step 2, but I wanted to make sure the Width didn't automatically change if I changed it from stretch to left (step 3)
  3.  Subscribe to the parent grid's size changed event (step 1) in the child grid's view model (or code behind)
    1. In this event handler, do the following
      1. If the local grid variable (set in the Loaded event) is null, return
      2. Set the local grid variable's Width to m_grid.Width - (e.PreviousSize.Width - e.NewSize.Width)
        1. Assume m_grid is the local grid variable, and e is the SizeChangedEventArgs

This will work and keep the child grid's width dynamic.  Again, this is a HUGE hack, and there has to be a better way to do it.  I'm just listing out one possible work-around.  Also, if you use Prism, you can use extensions for the grid loaded and grid size changed events so you can use commands in the view model without having to write anything in the code behind.  Also, if you don't have your parent & child split out into 2 user controls, then you don't need to raise/subscribe to an event as you can handle everything in one place (you would just need to store a list of grid objects as you can have multiple child grids displayed and perform the resize logic in step 3 for all grids in that list).

Again, any better approaches would be greatly appreciated.  Thanks.

0
Rossen Hristov
Telerik team
answered on 24 Feb 2010, 08:55 AM
Hi Devin Losee,

I have invented another workaround which might be simpler if you decide to use it.

1. Upgrade to our Latest Internal Build version.

For Parent Grid:
2. Replace ColumnsWidthMode (obsolete) with the new property ColumnWidth="*"

For the row details grid:
3. Replace ColumnsWidthMode (obsolete) with ColumnWidth="Auto". Placing "*" here causes this weird stretching.

We hope that this workaround will do for now.

Meanwhile, we will continue investigating what is the reason for this weird glitch. By the way I saw it -- in the first instant everything looks fine and then something happens and stretches the grid to the right. Some layout update is going on and feeding a new very large width to the MeasureOverride method of the grid, but we are still unable to catch who and why measures the grid with such a huge width. We suspect it has to do something with the fact that everything is inside a ScrollViewer. But we will continue debugging and I hope that we catch the offender.

I have attached the sample project with the latest binaries and the changes I described above.

Please, excuse us for the inconvenience and thank you for your understanding.

Regards,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Devin Losee
Top achievements
Rank 1
answered on 24 Feb 2010, 01:53 PM
This works a lot better.  At least the vertical scrollbar is working as it should.  The only problem is you can't set the columns width mode to fill (or use * in the column width).  If you have lots of columns, it will probably force the width of the child grid to be larger than the width of the parent.  Again, this is much better than before, thanks.  I do look forward to any updates you may find on this issue. Let me know if I should mark your last post as an answer or if I should leave this open until it is completely resolved. 
0
Devin Losee
Top achievements
Rank 1
answered on 24 Feb 2010, 02:25 PM
Actually, I did notice one thing about the binaries you sent.  If I drag one of the child grid headers up to the grouping panel, it causes an exception (Line 53; System.InvalidOperationException: MeasuerOverride of element 'Telerik.Windows.Controls.GridView.GridViewVirtualizingPanel' should not return PositiveInfinity or NaN as its desired size. at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)).
0
Rossen Hristov
Telerik team
answered on 25 Feb 2010, 01:19 PM
Hello Devin Losee,

We understood what is going on and why the child grid becomes 2-3 screens wide.

Let me try to explain what is going on and what are the difference between our implementation and that of the MS DataGrid.

1. Our DetailsPresenter (the parent of whatever is defined inside the RowDetailsTemplate) is measured with Infinity. We do not want to restrict the width of the DetailsPresenter to be equal to the parent grid width. This means that the DetailsGrid which is the one and only child of the DetailsPresenter will be measured with Infinity.

2. Now, when you make the second column of the DetailGrid be a star (*), i.e. fill all available space, this is what happens. It asks: How many space do I have? The answer is: Infinite. This is because you have not defined explicit width for your DetailGrid and there is not explicit width defined anywhere if you climb up on the three of visual parents.

3. So the second column of the DetailsGrid wants to become infinite in width. Luckily, we coerce all column widths to be less than 10'000 pixels. That is why this column becomes around three monitor screens wide, i.e. 10'000 pixels.

4. Now if you really want to use a star column (i.e. Fill mode) you will have to set the Width of the DetailGrid to something explicit, for example 600. Or anything else.

5. This is important. You mentioned that all of this works fine with the MS DataGrid. I am not sure how you were able to achieve a DetailGrid with column fill mode using the MS DataGrid. They do not have this option. The MS DataGrid does not support star (*) columns. Which of course saves them from this configuration.

6. Another thing I have noticed is that you are setting these two on the ParentGrid:
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"

This will not work. In the moment that you place RadGridView inside an infinite container, such as the ScrollViewer, it will never ever have scroll-bars of its own. It will get all the space it wants (since it is inside a ScrollViewer) and it will never need to show scroll-bars. So you can remove those two. They do absolutely nothing.

So until we provide a solution for the case that you have hit, your two options are:

A. Avoid using star (*) width columns in the DetailGrid when its width is infinite.

B. Specify an explicit width for the DetailGrid, so that its star columns work properly.

C. There is another possibility, but it is a hack and I do not recommend it. Anyway I will share it with you. You can do this:

private void ParentGrid_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var parentGrid = sender as RadGridView;
            if (parentGrid != null)
            {
                var childGrids = parentGrid.ChildrenOfType<RadGridView>();
                foreach (var childGrid in childGrids)
                {
                    childGrid.Width = parentGrid.DesiredSize.Width
                        - (childGrid.Margin.Left + childGrid.Margin.Right);
                }
            }
        }

This will keep the parent and child grid widths in sync. But I do not recommend it. There may be side effects from this.

Anyway, since your case is valid we will try to come up with a built-in solution for such cases.

Unfortunately, I cannot provide an exact time frame. Thank you for your understanding.

Regards,
Ross
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Tags
GridView
Asked by
Devin Losee
Top achievements
Rank 1
Answers by
Devin Losee
Top achievements
Rank 1
Rossen Hristov
Telerik team
Share this question
or