Skip to main content
Home Forums Silverlight Programming Report a Silverlight Bug DataGrid Row Auto-Resize only grows row height but won't shrink
13 replies. Latest Post by dgonth on November 14, 2009.
(0)
dgonth
Member
2 points
3 Posts
02-06-2009 3:51 PM |
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.
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
27 points
101 Posts
08-27-2009 10:25 PM |
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!
praveenr...
42 points
14 Posts
08-28-2009 2:55 PM |
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
08-29-2009 9:46 AM |
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 notshrink 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 part2collapsed and uncollapsed, but did not get SizeChanged on the "theContainer".
rusmo27
4 points
5 Posts
09-02-2009 8:27 AM |
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
112 points
70 Posts
10-05-2009 7:44 AM |
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
422 points
126 Posts
10-11-2009 5:00 PM |
in the xaml near the top add
<UserControl.Resources> <local:dgPlanRowHeight x:Key="dgPlanRowHeight" />
in the xaml for the grid definition add
RowHeight
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
24 points
34 Posts
10-15-2009 5:59 PM |
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?
10-19-2009 11:15 AM |
I did some more work on this
1 - subclass the grid
End
2 - track when you add / remove rows
XAML
<local:MyDataGrid x:Name="dgPlan"
VB
e.Row.DataContext.expanded =
dgPlan.GridRow.Add(e.Row)
' set height here based on condition
e.Row.Height = 20
dgPlan.GridRow.Remove(e.Row)
or set height later - button click (button is in the row in the grid) in this case
lIndex = m_oPlanList.IndexOf(cmdButton)
aRow = dgPlan.GridRow(lIndex)
aPlan = m_oPlanList(lIndex)
aPlan.Expanded =
aRow.Height = 25
else
aPlan.Expanded = True
aRow.Height = 200
End if
11-01-2009 7:33 PM |
here's a simple solution
background
dgPlan.itemssource = observable collection of clsPlan
<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
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.DataContextThe 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
6 Posts
11-05-2009 4:33 PM |
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?
11-05-2009 5:19 PM |
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
1 Posts
11-13-2009 10:50 PM |
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(); } }
11-14-2009 9:19 AM |
As far as I can tell the original problem I reported with the row heights was fixed in Silverlight 3.