This project is read-only.
1

Resolved

CODE.Framework.Wpf.Layout.ColumnDefinitions is not null but count is 0

description

Hi,
in the following methods ColumnDefinitions property is checked against whether it is null or not however not the count > 0 so they are crashing in some cases, and I have updated their code with the following and now it is working perfect
MeasureOverride method as follows
        protected override Size MeasureOverride(Size availableSize)
        {
            var infinity = new Size(double.PositiveInfinity, double.PositiveInfinity);
            var totalColumns = ColumnDefinitions == null ? 1 : ColumnDefinitions.Count;
            var columnWidths = GetActualColumnWidths(availableSize.Width);
            var maxHeight = 0d;
            if (ColumnDefinitions != null )
                foreach (UIElement child in Children)
                {
                    var columnIndex = Math.Min(GetColumn(child), totalColumns);
                    
                        if (ColumnDefinitions.Count > 0 && ColumnDefinitions[columnIndex].Visible == Visibility.Visible)
                        {
                            child.Measure(infinity);
                            maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
                            if (!ColumnDefinitions[columnIndex].Width.IsAbsolute)
                                columnWidths[columnIndex] = Math.Max(columnWidths[columnIndex], child.DesiredSize.Width);
                        }
                }

            return new Size(columnWidths.Sum(), maxHeight);
        }

And ArrangeOverride method is
        protected override Size ArrangeOverride(Size finalSize)
        {
            var actualColumnWidths = GetActualColumnWidths(finalSize.Width);
            var totalColumns = actualColumnWidths.Length;

            var columnLefts = new double[actualColumnWidths.Length];
            var currentLeft = 0d;
            for (var columnCounter = 0; columnCounter < columnLefts.Length; columnCounter++)
            {
                columnLefts[columnCounter] = currentLeft;
                currentLeft += actualColumnWidths[columnCounter];
            }

            foreach (UIElement child in Children)
            {
                if (child == null) continue;
                var columnIndex = Math.Min(GetColumn(child), totalColumns);
                if (ColumnDefinitions != null && ColumnDefinitions.Count > 0 && ColumnDefinitions[columnIndex].Visible == Visibility.Visible)
                {
                    if (ColumnDefinitions[columnIndex].AutoShowChildElement)
                        child.Visibility = Visibility.Visible;
                    var renderRect = new Rect(columnLefts[columnIndex], 0d, actualColumnWidths[columnIndex], finalSize.Height);
                    child.Arrange(renderRect);
                }
                else
                    child.Visibility = Visibility.Collapsed;
            }

            return finalSize;
        }

comments

MarkusEgger wrote Nov 25, 2014 at 8:43 AM

Very good catch! Thank you for reporting this! I have incorporated your change. This will be included in the next build.

Thanks,
Markus

wrote Nov 25, 2014 at 8:44 AM

rahulpatil2009 wrote Dec 17, 2014 at 10:48 AM

if we add the check 'count>0' outside the loop the solution will be more efficient, like below:
protected override Size MeasureOverride(Size availableSize)
        {
            var infinity = new Size(double.PositiveInfinity, double.PositiveInfinity);
            var totalColumns = ColumnDefinitions == null ? 1 : ColumnDefinitions.Count;
            var columnWidths = GetActualColumnWidths(availableSize.Width);
            var maxHeight = 0d;
            if (ColumnDefinitions != null && totalColumns > 0)
                foreach (UIElement child in Children)
                {
                    var columnIndex = Math.Min(GetColumn(child), totalColumns);
                    if (ColumnDefinitions[columnIndex].Visible == Visibility.Visible)
                    {
                        child.Measure(infinity);
                        maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
                        if (!ColumnDefinitions[columnIndex].Width.IsAbsolute)
                            columnWidths[columnIndex] = Math.Max(columnWidths[columnIndex], child.DesiredSize.Width);
                    }
                }

            return new Size(columnWidths.Sum(), maxHeight);
        } 
And
protected override Size ArrangeOverride(Size finalSize)
        {
            var actualColumnWidths = GetActualColumnWidths(finalSize.Width);
            var totalColumns = actualColumnWidths.Length;

            var columnLefts = new double[actualColumnWidths.Length];
            var currentLeft = 0d;
            for (var columnCounter = 0; columnCounter < columnLefts.Length; columnCounter++)
            {
                columnLefts[columnCounter] = currentLeft;
                currentLeft += actualColumnWidths[columnCounter];
            }

            if (ColumnDefinitions.Count > 0)
            {
                foreach (UIElement child in Children)
                {
                    if (child == null) continue;
                    var columnIndex = Math.Min(GetColumn(child), totalColumns);
                    if (ColumnDefinitions[columnIndex].Visible == Visibility.Visible)
                    {
                        if (ColumnDefinitions[columnIndex].AutoShowChildElement)
                            child.Visibility = Visibility.Visible;
                        var renderRect = new Rect(columnLefts[columnIndex], 0d, actualColumnWidths[columnIndex], finalSize.Height);
                        child.Arrange(renderRect);
                    }
                    else
                        child.Visibility = Visibility.Collapsed;
                }
            }

            return finalSize;
        }

MarkusEgger wrote Jan 17, 2015 at 3:59 PM

Mmmm... but this isn't exactly right, is it? If ColumnDefinitions is not null, but the count is 0, we still have to treat it as a single column.

Markus

rahulpatil2009 wrote Jan 19, 2015 at 1:11 PM

Hi Markus,

My solution is right for the first method 'MeasureOverride()'. But not correct for second method 'ArrangeOverride()' which has 'Else' part which must be executed for every element. I did not notice that. My apologies!

Regards,
Rahul