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
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;
}
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!
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
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".
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.
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
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?
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
' 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.
dgonth
Member
4 Points
4 Posts
DataGrid Row Auto-Resize only grows row height but won't shrink
Feb 06, 2009 07:51 PM | LINK
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.
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.csdatagrid DataGrid Row Auto Resizing
rich_r26
Member
27 Points
102 Posts
Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Aug 28, 2009 02:25 AM | LINK
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!
praveenranga...
Member
42 Points
14 Posts
Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Aug 28, 2009 06:55 PM | LINK
rich_r26
Member
27 Points
102 Posts
Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Aug 29, 2009 01:46 PM | LINK
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
Member
9 Points
14 Posts
Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Sep 02, 2009 12:27 PM | LINK
BKrishna
Member
112 Points
70 Posts
Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Oct 05, 2009 11:44 AM | LINK
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
Participant
1614 Points
357 Posts
Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Oct 11, 2009 09:00 PM | LINK
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
Member
24 Points
34 Posts
Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Oct 15, 2009 09:59 PM | LINK
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
Participant
1614 Points
357 Posts
Re: Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Oct 19, 2009 03:15 PM | LINK
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
Class2 - 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 Thene.Row.DataContext.expanded =
True Elsee.Row.DataContext.expanded =
False End IfdgPlan.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 Subor 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 DataGridRowaRow = dgPlan.GridRow(lIndex)
Dim aPlan As WorkView.PlanSupportServiceReference1.clsPlanlIndex = m_oPlanList.IndexOf(cmdButton)
aPlan = m_oPlanList(lIndex)
If aPlan.Expanded ThenaPlan.Expanded =
FalseaRow.Height = 25
else
aPlan.Expanded = True
aRow.Height = 200
End if
estern
Participant
1614 Points
357 Posts
Re: Re: Re: Re: Re: Re: DataGrid Row Auto-Resize only grows row height but won't shrink
Nov 01, 2009 11:33 PM | LINK
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.