Bug with DataGrid.HeadersVisibility?

Feb 13, 2009 at 10:16 AM
I have set the DataGrid.HeadersVisibility to "Column" and it seems to be working fine at first. The problem is that sometimes when I scroll, or maximize the window, one or two rows suddenly get a row header (which makes them look "unaligned"). The row headers disappear when I scroll them out of view, but may reappear at different places if I keep scrolling up and down.

Any ideas about this one?
Feb 19, 2009 at 10:08 AM
I never found out what was causing this, but if anyone else runs into the same problem I "solved" it by removing the control template for the DataGridRowHeader. Like this:

 

 

<Style TargetType="{x:Type dg:DataGridRowHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="dg:DataGridRowHeader" />
        </Setter.Value>
    </Setter>
</Style>

 

Coordinator
Feb 19, 2009 at 6:37 PM
Hi xyph,

This sounds like it could be due to a bug in our container recycling, though I'm not sure why removing the template would fix it.  Also, I'm not able to reproduce this with any of our test apps.  Could you post a small app which repros the problem?

Thanks,
Samantha
Feb 20, 2009 at 8:44 AM
Hi Samantha,

I created a small dummy-app which is able to reproduce the behavior. I uploaded it here:
http://rapidshare.com/files/200278556/DataGridRowHeaderBug.zip.html

I also made a screenshot:
http://sv.tinypic.com/view.php?pic=t6702e&s=5

My idea was that removing the control template would prevent it from showing up visually, though I am sure it's "still there".
Coordinator
Feb 26, 2009 at 11:37 PM
Thanks so much for sending along the repro, xyph.  I'm not sure what's going on, but I've noticed that it only happens when row virtualization is turned on and SelectionMode=Extended.  I've filed a bug in our internal database to track this and see if we can figure out what exactly is causing the problem.

Thanks!
Samantha
Mar 31, 2009 at 10:37 AM
Sorry to awaken an old thread but I just discovered that this bug also affects column resizing. If I resize a column and scroll down some of the rows may still have the old width, and look unaligned.

Like this:
http://sv.tinypic.com/view.php?pic=5y86c2&s=5

Any ideas about a work-around for this one?
Feb 10, 2010 at 8:54 PM
samanthamsft wrote:
Thanks so much for sending along the repro, xyph.  I'm not sure what's going on, but I've noticed that it only happens when row virtualization is turned on and SelectionMode=Extended.  I've filed a bug in our internal database to track this and see if we can figure out what exactly is causing the problem.

Thanks!
Samantha

Any Update on the Bug?

Is this fixed in .Net 4 (VS 2010)?

Thanks!

Jun 7, 2010 at 9:12 AM
samanthamsft wrote:
Thanks so much for sending along the repro, xyph.  I'm not sure what's going on, but I've noticed that it only happens when row virtualization is turned on and SelectionMode=Extended.  I've filed a bug in our internal database to track this and see if we can figure out what exactly is causing the problem.

Thanks!
Samantha

 Hey, just found it's not resolved int .Net4.0, so I am wondering if there are any fix?

And what's going on for wtf toolkit, seems not updated for a long time.

Jan 21, 2011 at 9:17 PM
Edited Jan 24, 2011 at 3:21 PM

I have the same problem, even with SelectionMode="Single".  The only fix I've found is to set HeadersVisibility="All" and RowHeaderWidth="0".

Jul 11, 2011 at 4:32 PM
Edited Jul 12, 2011 at 10:31 AM

Until the bug has been resolved, here's a possible workaround that did solve the issues in my case. You might have to repeat the solution for other parts of the source code which did not happen to be problematic for me.

I encountered the following data binding errors:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=AreRowDetailsFrozen; DataItem=null; target element is 'DataGridDetailsPresenter' (Name=''); target property is 'SelectiveScrollingOrientation' (type 'SelectiveScrollingOrientation') 
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=HeadersVisibility; DataItem=null; target element is 'DataGridRowHeader' (Name=''); target property is 'Visibility' (type 'Visibility') 

After doing some research, I discovered that the databinding engine is not always able to find the owning DataGrid via the 'RelativeSource FindAncestor' mechanism when it is using virtualization (which is the default behavior). These bindings are part of the control template of the DataGridRow. It seems like the bindings are evaluated before the DataGridRow is actually added to the VisualTree or had its parent set (and thus the FindAncestor is not able to find the owning DataGrid).

In virtualized mode, a DataGridRow 'knows' the concept of preparation (and recycling). Although the source code would suggest that DataGridRows are not tighlty coupled to a DataGrid, in practice they are. There is even an Diagnostic.Assert check present in the DataGrid's source code that validates that the DataGrid for which the row is prepared is the same as for which it has been used. The owning DataGrid is also available als internal property.

With this knowledge, I altered the control template of the DataGridRow not to use the 'RelativeSource FindAncestor' mechanism but directly bind to the DataGridOwner property of the DataGridRow This removes all of the data binding errors mentioned:

  • I changed the accessability of the existing DataGridOwner property of the DataGridRow from internal to public.
  • I modified the bindings of following section of the control template of the DataGridRow style in Generic.xaml in the following way:

Original

 

<dgp:DataGridDetailsPresenter dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static dg:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static dg:SelectiveScrollingOrientation.Vertical}}"
                                            Grid.Column="1" Grid.Row="1"
                                            Visibility="{TemplateBinding DetailsVisibility}" />
              
<dgp:DataGridRowHeader dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"  Grid.RowSpan="2"
                                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=HeadersVisibility, Converter={x:Static dg:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static dg:DataGridHeadersVisibility.Row}}"/>

Modified 

<dgp:DataGridDetailsPresenter dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding Path=DataGridOwner.AreRowDetailsFrozen, Converter={x:Static dg:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static dg:SelectiveScrollingOrientation.Vertical}}"
                                            Grid.Column="1" Grid.Row="1"
                                            Visibility="{TemplateBinding DetailsVisibility}" />
              
<dgp:DataGridRowHeader dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"  Grid.RowSpan="2"
                                    Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dg:DataGridRow}}, Path=DataGridOwner.HeadersVisibility, Converter={x:Static dg:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static dg:DataGridHeadersVisibility.Row}}"/>

 

I hope this helps some of you. 

Dec 2, 2011 at 11:24 AM

I've the same problem, as workaround I've created a global DataGrid style with this trigger:

<Style.Triggers>
     <Trigger
        Property="HeadersVisibility"
        Value="Column">         
          <Setter
             Property="RowHeaderWidth"
             Value="0" />
     </Trigger>
</Style.Triggers>

Mar 22, 2012 at 6:55 PM
Edited Mar 22, 2012 at 7:05 PM

@jdebekker:

I couldn't get that solution to work for me precisely with the .Net 4.0 DataGrid.  I had to do the following for the second binding (though now it is inexplicably a hack):

<DataGridRowHeader SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                               Grid.RowSpan="2"
                                               Visibility="{Binding RelativeSource={RelativeSource Self}, Path=Parent.Parent.Parent.DataGridOwner.HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}" />

To be precise, the binding wasn't finding the DataGridOwner property on DataGridRow if I used the below (I have no idea why)

AncestorType={x:Type dg:DataGridRow}

 


 

Feel free to use this posted code for anything, just don't blame me.

Mar 23, 2012 at 2:41 PM

@skybluecodeflier

Regretfully, my solution was targeting .NET 3.5 SP1 in combination with the DataGrid from the WPFToolkit. Until today I haven't used the DataGrid from .NET 4.0...At least you have found a workaround yourself :)

Apr 5, 2012 at 9:00 PM

@skybluecodeflier:

Can you please give me some more details of your workaround?  I am running into this binding error (and occasional row header flicker) with the .NET 4.0 DataGrid and since that means I don't have direct access to the source for the DataGrid I'm not sure how to fix this.  I tried the other solutions suggested (style that sets controltemplate to nothing, setting RowHeaderWidth to 0, etc.) but I am still getting the error.  In my case I am using a grid to display the contents of a file, and I get the error if the file I load has enough in it to cause the grid to scroll.

For what it's worth, there are a lot of RelativeSource bindings in the WPF default styles and templates that fail frequently (like ComboBoxItem, ListBoxItem, etc.).  It would be great if Microsoft could eliminate those from the defaults.  Some of them I can get around with styles that include OverridesDefaultStyle = True, but some of them I've had to derive custom controls to fix.  The official answer of "they're transient, ignore them" is unsatisfying.  If it's not an error, it shouldn't be an error ever.