Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
232 views
in Technique[技术] by (71.8m points)

c# - Auto Height in combination with MaxHeight

I am facing a problem with setting the following xaml layout:

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>

The DataGrid1 control isn't showing any scrollbars with a lot of columns and rows defined. Everything works find when I would replace the Height="Auto" with Height="*" than Horizontal and Vertical scrollbars appear like expected.

Also it works when I would declare the MaxHeight directly at the DataGrid1, but that's not really want I want.

Is this a bug that the childcontrol ignores the maxheight on setting Height="Auto" or am I propably making something wrong? Same behaviour can be reproduced with ListBox/ListView and so on, also with third party controls like ComponentOne, Telerik...

If it's a bug - do you know a workaround or have other hints for me?

Here is the code how I set the ItemsSource of the 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; }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is exactly as you say it is.

The reason why you do not see the Scrollbar's is because even though the Grid Clip's the DataGrid, it's merely a Clip, the ActualHeight of the DataGrid is the height it would get if allowed to show all it's children. You are thus not seeing it's scrollbar's. ActualHeight is so cos it's allowed to get all the space it wants with Height="Auto" on the Grid. The reason I wouldn't call this a bug personally is cos you might desire this behavior if you want to play with the ClipToBounds property of the Grid for certain animations and this is the behavior you desire. Thinking about this, I actually think I'd call this a bug too in terms of "Not desirable functionality" than "Incorrect output"

To get the behavior your looking for,

  • Apply the MaxHeight on the DataGrid or use Grid RowDefinition.Height="*" <- both as you mentioned (Not sure why you say this is not what you want to do?)
  • Or you could also use a RelativeSourceBinding on the DataGrid

something like -

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

For such issues Snoop is your friend. You can easily check this behavior and realize why the scrollbar's aren't shown when you check the ActualHeight on your DataGrid using Snoop and see it allocates quite a bit more height to the child control.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...