7

I would like to know how many rows are actually displayed by a WPF DataGrid.

I tried looping over DataGridRow and checking IsVisible, but it seems that rows report IsVisible = true even when they are not in the DataGrid viewport.

How can I count the number of visible rows correctly?

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Amir Gonnen
  • 3,525
  • 4
  • 32
  • 61

4 Answers4

2

I've asked this question also on MSDN forum and got a good answer:

private bool IsUserVisible(FrameworkElement element, FrameworkElement container) {
    if (!element.IsVisible)
        return false;
    Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
    Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
    return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Amir Gonnen
  • 3,525
  • 4
  • 32
  • 61
  • return sentence should be changed to: return rect.Top < bounds.Top && rect.Bottom > bounds.Bottom; Then it will check if the whole item is displayed rather then top left corner or bottom right corner. – Audrius Gailius Sep 13 '22 at 10:53
1

I had the same problem with rows showing as Visible = true even when they weren't.

Trying to come up with a solution, I posted this question: Visible rows in DataGrid is off by 1 (counted using ContainerFromItem).

Here's what worked for me:

uint VisibleRows = 0;
var TicketGrid = (DataGrid) MyWindow.FindName("TicketGrid");

foreach(var Item in TicketGrid.Items) {
    var Row = (DataGridRow) TicketGrid.ItemContainerGenerator.ContainerFromItem(Item);

    if(Row != null) {
        if(Row.TransformToVisual(TicketGrid).Transform(new Point(0, 0)).Y + Row.ActualHeight >= TicketGrid.ActualHeight) {
            break;
        }

        VisibleRows++;
    }
}

For further guidance, there are some /* comments */ in my answer on the linked question, as well as a thread of user comments on the question itself that led to the answer.

Community
  • 1
  • 1
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
0

a simple hack come to mind,

loop over all rows and check if item has a container?

dataGrid.GetContainerFromItem(dataGrid.Items[row]);

hope this helps

Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
  • 1
    This does not work. In fact, in my loop I was using `ItemContainerGenerator.ContainerFromIndex` and some items that are not displayed still have container. – Amir Gonnen May 12 '11 at 15:44
0

If you need it for another xaml element just add a reference via "ElementName" and the property via "Items.Count" to your content property(in this case "Text"). You might also use a converter to parse the value.

<TextBlock Text="{Binding ElementName=ComponentDataGrid, Path=Items.Count, Converter={StaticResource IntToStringConverter}}"/>
Noel
  • 1
  • 1