Автоматическая высота в сочетании с MaxHeight

У меня возникла проблема с настройкой следующего макета 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 = "*", чем горизонтальные и вертикальные полосы прокрутки, как ожидалось.

Также он работает, когда я объявляю MaxHeight непосредственно в DataGrid1, но этого действительно не хочу.

Является ли это ошибкой, что childcontrol игнорирует maxheight при установке Height = "Auto" или я могу сделать что-то неправильно? То же поведение можно воспроизвести с помощью ListBox/ListView и т.д., А также с сторонними элементами управления, такими как ComponentOne, Telerik...

Если это ошибка - знаете ли вы обходной путь или имеете другие подсказки для меня?

Вот код, как я устанавливаю ItemsSource DataGrid. 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; }

}

Ответы

Ответ 1

Это точно так, как вы говорите.

Причина, по которой вы не видите Scrollbar, состоит в том, что даже если Grid Clip the DataGrid, это просто клип, ActualHeight DataGrid - это высота, которую он получит, если разрешено чтобы показать все это детям. Таким образом, вы не видите его полосу прокрутки. ActualHeight, так что это позволило получить все необходимое пространство с Height="Auto" на Grid. Причина, по которой я бы не назвал это ошибкой лично, потому что вы можете захотеть этого поведения, если хотите сыграть с свойством ClipToBounds для Grid для определенных анимаций, и это поведение, которое вы желаете. Думаю об этом, я на самом деле думаю, что я бы назвал это ошибкой тоже с точки зрения "Нежелательной функциональности", чем "Неправильный вывод"

Чтобы получить поведение, которое вы ищете,

  • Примените MaxHeight к DataGrid или используйте Grid RowDefinition.Height="*" < - оба, как вы упомянули (не знаете, почему вы говорите, что это не то, что вы хотите сделать?)
  • Или вы также можете использовать RelativeSourceBinding на DataGrid

что-то вроде -

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

Для таких проблем Snoop - ваш друг. Вы можете легко проверить это поведение и понять, почему полоса прокрутки не отображается, когда вы проверяете ActualHeight на вашем DataGrid с помощью Snoop и видите, что дочерний элемент выделяет достаточно большую высоту.