自动高度与最大高度相结合

本文关键字:高度 相结合 | 更新日期: 2023-09-27 18:23:49

我在设置以下xaml布局时遇到问题:

RowHeightAuto.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="GridMaxHeight.RowHeightAuto"
    Title="RowHeightAuto" WindowState="Maximized">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" MaxHeight="200" />
    </Grid.RowDefinitions>
    <StackPanel Background="LightGray" Grid.Row="0"></StackPanel>
    <DataGrid Name="DataGrid1" Grid.Row="1" />
</Grid>

DataGrid1控件没有显示任何定义了大量列和行的滚动条。当我将Height="Auto"替换为Height="*"时,一切都会正常,而不是像预期的那样显示水平和垂直滚动条。

当我直接在DataGrid1中声明MaxHeight时,它也会起作用,但这并不是我真正想要的。

这是子控件在设置Height="Auto"时忽略最大高度的错误吗?还是我可能做错了什么?同样的行为可以用ListBox/ListView等再现,也可以用第三方控件(如ComponentOne、Telerik。。。

如果这是一个bug,你知道变通方法吗?或者有其他提示吗?

以下是我如何设置DataGrid的ItemsSource的代码。RowHeightAuto.xaml.cs

public partial class RowHeightAuto : Window
{
    private readonly DateTime _start;
    public RowHeightAuto()
    {
        InitializeComponent();
        DataGrid1.ItemsSource = GetTestData();
        _start = DateTime.Now;
        Dispatcher.BeginInvoke(new Action(() => MessageBox.Show((DateTime.Now - _start).TotalSeconds.ToString(CultureInfo.InvariantCulture))), DispatcherPriority.ContextIdle, null);
    }
    public static List<TestData> GetTestData()
    {
        const int maxCols = 501;
        const int maxRows = 300;
        var testDatas = new List<TestData>(maxRows);
        for (int i = 0; i < maxRows; i++)
            testDatas.Add(new TestData());
        for (int i = 0; i < maxCols; i++)
        {
            string propName = string.Format("Property{0}", AddLeadingZeros(i));
            for (int j = 0; j < maxRows; j++)
                testDatas[j][propName] = propName;
        }
        return testDatas;
    }
    private static string AddLeadingZeros(int val)
    {
        return val.ToString(CultureInfo.InvariantCulture).PadLeft(3, '0');
    }
}
public class TestData
{
    public object this[string propertyName]
    {
        get
        {
            var myType = GetType();
            var myPropInfo = myType.GetProperty(propertyName);
            return myPropInfo.GetValue(this);
        }
        set
        {
            var myType = GetType();
            var myPropInfo = myType.GetProperty(propertyName);
            myPropInfo.SetValue(this, value, null);
        }
    }
    public string Property000 { get; set; }
    public string Property001 { get; set; }
    public string Property002 { get; set; }
    public string Property003 { get; set; }
    ...
    public string Property498 { get; set; }
    public string Property499 { get; set; }
    public string Property500 { get; set; }
}

自动高度与最大高度相结合

这正是你所说的。

您之所以看不到Scrollbar的,是因为即使Grid剪辑是DataGrid,它也只是一个剪辑,而DataGridActualHeight是如果允许显示其所有子级时它将获得的高度。因此,您没有看到它的滚动条。ActualHeight之所以如此,是因为它可以通过Grid上的Height="Auto"获得它想要的所有空间我个人不会称之为bug的原因是,如果你想在某些动画中使用GridClipToBounds属性,你可能会想要这种行为,而这正是你想要的行为考虑到这一点,我实际上认为我也会称之为"不理想的功能"而不是"不正确的输出"的错误

为了得到你想要的行为,

  • DataGrid上应用MaxHeight或使用网格RowDefinition.Height="*"<-正如你提到的(不确定你为什么说这不是你想做的?)
  • 或者您也可以在DataGrid上使用RelativeSourceBinding

类似

<DataGrid Name="DataGrid1" 
          Grid.Row="1"
          Height="{Binding RelativeSource={RelativeSource FindAncestor,
                           AncestorType={x:Type Grid}},
                           Path=RowDefinitions[1].ActualHeight}">

对于此类问题,Snoop是您的朋友。当您使用Snoop检查DataGrid上的ActualHeight并看到它为子控件分配了更多的高度时,您可以很容易地检查这种行为,并了解为什么滚动条没有显示。