在WPF数据表格中查找行高

5

请问有人能告诉我如何做到这一点吗?

我已经尝试过了。

dtgMain.RowHeight;

但是这总是返回NAN。

它返回NaN是因为它已被明确设置(您的行高始终根据其内容假定。一旦设置,它将返回该值)。 - user572559
有没有办法找到行的假定高度是多少? - user589195
只是 NaN 而已 - 在 WPF 中,元素允许具有 NaN 作为高度,这意味着大小由内容决定,而不是明确指定。您可以尝试调用 Measure(double.PositiveInfinity, double.PositiveInfinity) 并在之后检查 DesiredSize。但不能保证一定有效。 - user572559
6个回答

5
使用VisualTreeHelper从数据网格中获取DataGridRow。然后使用DataGridRow的ActualHeight属性。
public static T GetFirstVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                return (T)child;
            }

            T childItem = GetFirstVisualChild<T>(child);
            if (childItem != null) return childItem;
        }
    }

    return null;
}

然后:

DataGridRow row = GetFirstVisualChild<DataGridRow>(dtgMain);
if(row != null)
{
    row.ActualHeight;
}

在调用 GetFirstVisualChild<DataGridRow>(dtgMain) 时,您是否指定了类型? - Amit
错误出现在 GetFirstVisualChild 方法的这一行。- T childItem = GetFirstVisualChild(child); - user589195
应该是 T childItem = GetFirstVisualChild<T>(child); 我已经更新了答案。谢谢。 - Amit
DataGridRow row = GetFirstVisualChild<DataGridRow>(dtgMain); 返回 null... 有任何想法吗? - user589195
如果数据表格中没有任何行,则它将为空。只有在数据表格中有一些行时才使用此方法。 - Amit
显示剩余4条评论

3

如果有人需要VB.NET版本...

Public Shared Function GetFirstVisualChild(Of T As DependencyObject)(depObj As DependencyObject) As T
    If (depObj IsNot Nothing) Then
        Dim i As Integer
        For i = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1

            Dim child As DependencyObject = VisualTreeHelper.GetChild(depObj, i)
            If (child IsNot Nothing AndAlso TypeOf child Is T) Then

                Return CType(child, T)
            End If

            Dim childItem As T = GetFirstVisualChild(Of T)(child)
            If (childItem IsNot Nothing) Then Return childItem
        Next
    End If
    Return Nothing
End Function

那么

Dim row As DataGridRow = CType(GetFirstVisualChild(Of DataGridRow)(grid), DataGridRow)

1
这很可能是因为网格尚未呈现。在尝试获取行高之前,请检查测量和排列函数以呈现网格。

我认为这可能是问题所在,并尝试使网格无效以强制其呈现。您能否请提供一小段代码示例? - user589195

1

这是NaN,因为你没有定义它。如果你不手动设置它,它将由行内容的测量结果定义。


你能稍微详细地解答一下吗? - user589195

0
这是一个作为扩展方法的函数。
public static T GetFirstVisualChild<T>(this DependencyObject depObj) where T : DependencyObject
{
    if (depObj == null) return null;

    for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
    {
        var child = VisualTreeHelper.GetChild(depObj, i);
        if (child is T tChild)
        {
            return tChild;
        }

        var childItem = GetFirstVisualChild<T>(child);
        if (childItem != null) return childItem;
    }

    return null;
}

除非您明确指定DataGridRowHeight,否则它将被设置为double.NaN。如果您想设置高度,最简单的方法是使用DataGridItemContainerStyle属性:
<DataGrid.ItemContainerStyle>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="Height" Value="30" />
    </Style>
</DataGrid.ItemContainerStyle>

如果您不想显式设置Height,那么您可以使用ActualHeight属性。区别在于Height是行的允许高度,而ActualHeight是渲染后的高度。
var row = grid.GetFirstVisualChild<DataGridRow>();

MessageBox.Show($"{row.ActualHeight}");

0
必须显示行。 挑战在于获取有效的DataGridRow实例,以便访问ActualHeight属性。 如果在启动时进行操作,可以默认为0,如下所示。 在发布的代码中,我获取行的高度,假设它们都具有相同的高度,以获取显示行数的指示(我取80%以获得近似值)。
            int currentRow = _grid.SelectedIndex == -1 ? 0 : _grid.SelectedIndex;
            System.Windows.DependencyObject  dep = _grid.ItemContainerGenerator.ContainerFromIndex(currentRow);
            var dataGridRow = dep as  DataGridRow;
            if (dataGridRow is null)
            {
                string msg = $"Cannot acces row[{currentRow}] of datagrid";
                _log.Error(msg);
                throw new AccessViolationException(msg);
            }
            int visibleRowCount = (int)(_grid.ActualHeight / dataGridRow.ActualHeight * 0.8);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接