Skip to main content

Microsoft Silverlight

DataGrid Row Auto-Resize only grows row height but won't shrinkRSS Feed

(0)

dgonth
dgonth

Member

Member

2 points

3 Posts

DataGrid Row Auto-Resize only grows row height but won't shrink

Using the latest December 2008 release of the DataGrid. 

When dynamically adding and removing items from a list embedded in a cell with autosize enabled for the row height there appears to be a bug in the DataGrid.  The DataGrid row will increase its height properly when items are added to the embedded list but the row height never decreases when the cell height shrinks after items are removed.  In my situation I am using an embedded ListBox but this appears to be a general problem anytime the row content height changes dynamically.

Extra Details

------------------ 

I took a look at the DataGrid source code released recently at

http://www.microsoft.com/downloads/details.aspx?FamilyID=EB83ED4C-AC85-4DE9-8395-285628EE2254&displaylang=en

I traced this behavior to a line in the MeasureOverride method of the DataGridCellsPresenter class.

if (autoSizeHeight)
{
   this.DesiredHeight = Math.Max(this.DesiredHeight, cell.DesiredSize.Height);
}

Because this.DesiredHeight is never reset the row always stays at the max height it has seen.

 It looks like this.DesiredHeight should have been reset to 0 up above in the method in order to get the row to shrink properly when the content changes.  I'm not sure if this wouldn't break something else but it did fix the problem in the version of the DataGrid I had the source for.  (Unfortunately I don't believe this is the source for the Dec 2008 version of the DataGrid.  The older version still has some nasty bugs having to do with using popups while editing a cell that make it unusable for my app.) See the this.DesiredHeight=0 setting in the code snippet below for the resizing fix.Code snippet: DataGridCellsPresenter.cs
protected override Size MeasureOverride(Size availableSize)
{
  if (this.OwningGrid == null)
  {
    return base.MeasureOverride(availableSize);
  }
  
  bool autoSizeHeight;
  double measureHeight;
  
  if (double.IsNaN(this.OwningGrid.RowHeight))
  {
     // No explicit height values were set so we can autosize
     autoSizeHeight = true;
     measureHeight = double.PositiveInfinity;
     this.DesiredHeight = 0; // dgonth - Bug fix to autosize correctly.
   }
   else
   {
      this.DesiredHeight = this.OwningGrid.RowHeight;
      measureHeight = this.DesiredHeight;
      autoSizeHeight = false;
   }
 

rich_r26
rich_r26

Member

Member

27 points

101 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I'm using Silverlight 3. And having similar problem. I have a Control for the column's DataTemplate. And its parts could collaps and visible, then collaps again. After it becomes visible the row height increases but does not shrink after it collapsed. Is there solution for it? Thanks!

praveenrangarajan
praveenr...

Member

Member

42 points

14 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I faced this problem a long time back in SL2 and have since used this solution (works well with SL3 also) implement a IValueConverter for the Height with the function returning "0" or "Auto" depending on the bitflag. Let me explain. I have a property (int) that indicates the state of the Visibility (0 Collapsed, 1 Visible). The IValueConverter routine returns "0" if 0 and "Auto" if 1. This solution works perfectly. Let me know if you have the same success or need more help. Praveen

rich_r26
rich_r26

Member

Member

27 points

101 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I am not sure if I am following you. I have single column DataGrid, make it simple it is something like:

 <data:DataGrid.Columns>
                                <data:DataGridTemplateColumn >
                                    <data:DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate  >                                           
                                            <local:MyControl Height="Auto"
                                                VerticalAlignment="Stretch" HorizontalAlignment="Left"                                               
                                                VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                                        </DataTemplate>
                                    </data:DataGridTemplateColumn.CellTemplate>                               
                                </data:DataGridTemplateColumn>

In MyControl it has a few parts, someone collapsed.

<Border x:Name="theContainer">
<StackPanel>
        <Button x:Name="ShowHidePart2" Content="Click"/>
        <TextBlock x:Name="part1" Text="some text..." Height="100"/>
        <TextBlock x:Name="CollapeAndVisual_part2" Text="...show...hide..." Height="200" />
       
</StackPanel>
</Border>

The button ShowHidePart2 will control to show CollapeAndVisual_part2.
When uncollapse and collapse again, the DataGridRow's height does not
shrink and leaves some blank space.
In your solution where do you apply the IValueConverter? (I'm not sure what is the return 0 about).
And at what time is the best time to apply it? After click on the button when is the definit time
that the un-collapse or collapse is complete and the visual has its size re-setted? Strange is I saw the part2
collapsed and uncollapsed, but did not get SizeChanged on the "theContainer". 

rusmo27
rusmo27

Member

Member

4 points

5 Posts

Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I'm having a similar problem getting a Grid Row to resize based on the visibility of one of its content's controls. Looking forward to a solution. Thanks, Will.

BKrishna
BKrishna

Member

Member

112 points

70 Posts

Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

Did anyone find a solution to this? I have a expander control in my datagrid and I am facing same problem.

Praveen, Can you pls ellobrate of the solution that you discussed? 

estern
estern

Member

Member

422 points

126 Posts

Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

in the xaml near the top add

    <UserControl.Resources>
        <local:dgPlanRowHeight  x:Key="dgPlanRowHeight" />

in the xaml for the grid definition add

RowHeight="{Binding Converter={StaticResource dgPlanRowHeight}, Path=EXPANDED}"

note:  EXPANDED is a column in the class bound to the grid

In code

Public Class dgPlanRowHeight
    Implements IValueConverter
    Public Function Convert(ByVal value As Object, _
                ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert

        Dim bExpanded As Boolean = value
        If bExpanded Then
            Return "Auto"
        Else
            Return "20"
        End If
    End Function

    Public Function ConvertBack(ByVal value As Object, _
                ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Return Nothing ' use the default
    End Function

End Class 

 

robmaransky
robmaransky

Member

Member

24 points

34 Posts

Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I have been unable to make this solution work for me. Has anyone out there been able to work around this problem in Silverlight 3? I can't believe this issue still exists. The DataGrid is a key component in most business applications and this is not an obscure use case. Any time your CellEditTemplate is larger than your CellTemplate, you will see this issue. Can anyone at Microsoft hear us?

 Is there a fix out there that I am unaware of?

estern
estern

Member

Member

422 points

126 Posts

Re: Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

I did some more work on this

1 - subclass the grid

Partial Public Class MyDataGrid

Inherits DataGrid

Public GridRow As List(Of DataGridRow) = New List(Of DataGridRow) '

End Class

2 - track when you add / remove rows

XAML 

<local:MyDataGrid x:Name="dgPlan"

LoadingRow="dgPlan_LoadingRow" UnloadingRow="dgPlan_UnloadingRow"

 

VB 

Private Sub dgPlan_LoadingRow(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEventArgs)

If m_Expanded Then

e.Row.DataContext.expanded = True

Else

e.Row.DataContext.expanded = False

End If

dgPlan.GridRow.Add(e.Row)

' set height here based on condition 

e.Row.Height = 20

End Sub

 

Private Sub dgPlan_UnloadingRow(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEventArgs)

dgPlan.GridRow.Remove(e.Row)

End Sub

or set height later - button click (button is in the row in the grid) in this case

Private Sub cmdEC_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

Dim lIndex As Long

Dim cmdButton As Object = CType(e.OriginalSource, Button).DataContext()

lIndex = m_oPlanList.IndexOf(cmdButton)

Dim aRow As DataGridRow

aRow = dgPlan.GridRow(lIndex)

Dim aPlan As WorkView.PlanSupportServiceReference1.clsPlan

lIndex = m_oPlanList.IndexOf(cmdButton)

aPlan = m_oPlanList(lIndex)

If aPlan.Expanded Then

aPlan.Expanded = False

aRow.Height = 25

else

aPlan.Expanded = True

aRow.Height = 200

End if

estern
estern

Member

Member

422 points

126 Posts

Re: Re: Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink

here's a simple solution

background

dgPlan.itemssource = observable collection of clsPlan

XAML

                    <data:DataGrid x:Name="dgPlan"
                            LoadingRow="dgPlan_LoadingRow" 
Code

     ' set the row binding for the row height converter
    Private Sub dgPlan_LoadingRow(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEventArgs)

        ' create a row level binding - works for height or background row color or ...
        Dim aBinding As New Binding("Expanded")
        aBinding.ConverterParameter = e.Row.DataContext
        aBinding.Mode = BindingMode.OneWay


        Dim aHeightConverter As New dgPlanRowHeightConverter
        aBinding.Converter = aHeightConverter

        aBinding.ValidatesOnExceptions = True
        e.Row.SetBinding(DataGridRow.HeightProperty, aBinding)
    End Sub

Converter

Public Class dgPlanRowHeightConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, _
                ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert

        Dim aPlan As clsPlan = parameter

        If aPlan.Expanded Then
            Return aPlan.SomeVar * 20
        Else
            Return 20
        End If

    End Function

    Public Function ConvertBack(ByVal value As Object, _
                ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Return Nothing ' not implemented
    End Function

End Class

Notes

        Dim aBinding As New Binding("Expanded")
Expanded is a member of clsPlan.  It raises a notifypropertychanged event.  Binding to Expanded causes the converter to fire if expanded is changed anywhere.

        aBinding.ConverterParameter = e.Row.DataContext
The class bound to the row is passed to the converter as the "parameter".  The converter can now access anything in the class but still respond to a notifypropertychanged event.

 

 

 

 

 

 

quinean
quinean

Member

Member

4 points

6 Posts

DataGrid Row Auto-Resize only grows row height but won't shrink

 I'm able to resize the rows using methods similar to what has been suggested before, but I'm having another related problem... some of the contents in some cells are placed incorrectly after the resizing after editing is done.

 For instance, I've styled the cells so that there is a triangle on the left side of the cell, with a centered vertical alignment, to indicate cell focus. After the resizing, these indicators are no longer centered in the resized smaller cell (as they were before editing), but appear to be centered for the larger edting template. Any other content that is centered vertically exhibits the same problem.

 I've tried re-sizing the cells, but that does not seem to solve the issue. 

Has anyone got any insight for this problem?

quinean
quinean

Member

Member

4 points

6 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

 It looks like I've corrected the problem I mention above by binding the Height of the Root Grid in the DataGridCellStyle as well as vertically aligning this Grid to Top.

 

 

<Style x:Key="DataGridCellStyle1" TargetType="data:DataGridCell">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Cursor" Value="Arrow"/>
    <Setter Property="IsTabStop" Value="True"/>
   
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="data:DataGridCell">
          <Grid x:Name="Root" Background="Transparent" VerticalAlignment="Top">
            <Grid.Height>
              <Binding Path='HeightParam' Converter='{StaticResource MVRowHeightCon}'></Binding>
            </Grid.Height>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <vsm:VisualStateManager.VisualStateGroups>
              <vsm:VisualStateGroup x:Name="CurrentStates">
                <vsm:VisualStateGroup.Transitions>
                  <vsm:VisualTransition GeneratedDuration="0"/>
                </vsm:VisualStateGroup.Transitions>
                <vsm:VisualState x:Name="Regular"/>
                <vsm:VisualState x:Name="Current">
                  <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Opacity">
                      <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                  </Storyboard>
                </vsm:VisualState>
              </vsm:VisualStateGroup>
            </vsm:VisualStateManager.VisualStateGroups>
            <!--<Rectangle HorizontalAlignment="Stretch" x:Name="FocusVisual" VerticalAlignment="Stretch" IsHitTestVisible="false" Opacity="0" Stroke="#FF6677CC" StrokeThickness="1"/>-->           
            <ContentPresenter Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
            <Canvas x:Name="FocusVisual" Height="8" Width="6" HorizontalAlignment="Left" VerticalAlignment="Center" Opacity="0">
              <Polygon Points="0,0 6,4 0,8" Fill="#FF6677CC">
              </Polygon>
            </Canvas>
            <Rectangle x:Name="RightGridLine" VerticalAlignment="Stretch" Width="1" Grid.Column="1"/>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

 

 

 

 

MarkieL
MarkieL

Member

Member

2 points

1 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

Thanks for pointing me to the source code and pointing out the DesiredHeight problem. It helped me to come with the following solution to solve this problem without modifying the source code. I hope this helps someone:

    public static class DataGridExtender
    {
        /// <summary>
        /// Reset datagrid row height
        /// </summary>
        /// <param name="row"></param>
        public static void ResetRowHeight( this DataGrid grid, DataGridRow row )
        {
            // only for autosize rows
            if (!double.IsNaN(row.Height)) return;

            // store current rowheight
            double rowheight = grid.RowHeight;

            // fore recalculating row height
            grid.RowHeight = 0;
            row.UpdateLayout();

            // restore rowheight
            grid.RowHeight = rowheight;
            row.UpdateLayout();
        }

        /// <summary>
        /// Reset grid column widths
        /// </summary>
        /// <param name="grid"></param>
        public static void ResetColumnWidths(this DataGrid grid)
        {
            // get autosize columns
            List columns = new List();
            foreach (DataGridColumn column in grid.Columns)
                if (column.Width.IsAuto) columns.Add(column);

            // reset autosize
            foreach (DataGridColumn column in columns)
                column.Width = new DataGridLength(0);
            grid.UpdateLayout();

            // update autosize
            foreach (DataGridColumn column in columns)
                column.Width = DataGridLength.Auto;
            grid.UpdateLayout();
        }
    }

 

dgonth
dgonth

Member

Member

2 points

3 Posts

Re: DataGrid Row Auto-Resize only grows row height but won't shrink

As far as I can tell the original problem I reported with the row heights was fixed in Silverlight 3.

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities