WPF布局算法失败 - 控件将调整大小,但不会低于某个任意值

时间:2010-04-15 15:08:05

标签: wpf wpf-controls resize

我正在为客户开发一个应用程序,其中一个要求是能够进行约会,并以可视格式显示当前周的约会,就像在Google日历或Microsoft Office中一样。我在codeproject上发现了一篇很棒的(3部分)文章,其中他构建了一个“RangePanel”,并为每个“句点”(例如,工作日)组成一个。你可以在这里找到第1部分:

http://www.codeproject.com/KB/WPF/OutlookWpfCalendarPart1.aspx

代码显示,但似乎总体上选择任意高度值(440.04),并且不会在没有剪裁的情况下调整大小。我的意思是,窗口/容器将调整大小,但它只是切断控件的底部,而不是重新计算范围面板的高度,以及表示约会的范围面板中的控件。它会调整大小并重新计算更大的值,但不能更少。

代码方面,正在发生的事情是,当您调整大小低于该值时,首先使用正确的“新高度”调用MeasureOverride。但是,在调用ArrangeOverride方法时,它会传递与要安排的高度相同的440.04值。

我需要找到一个解决方案/解决方法,但是您可以提供的任何可能指导我查看的内容的信息也会非常感激(我理解当您没有这些时调试代码是多么令人沮丧)在你面前的代码库。:))

下面提供了各种排列和测量功能的代码。 CalendarView控件有CalendarViewContentPresenter,可处理多个句点。然后,句点有CalendarPeriodContentPresenter,它处理约会的每个“块”。最后,RangePanel有自己的实现。 (老实说,我对控件的工作方式仍然有点朦胧,所以如果我的解释有点模糊,我链接的文章可能会有更有说服力的解释。:))

CalendarViewContentPresenter

    protected override Size ArrangeOverride(Size finalSize)
    {
        int columnCount = this.CalendarView.Periods.Count;
        Size columnSize = new Size(finalSize.Width / columnCount, finalSize.Height);
        double elementX = 0;

        foreach (UIElement element in this.visualChildren)
        {
            element.Arrange(new Rect(new Point(elementX, 0), columnSize));
            elementX = elementX + columnSize.Width;
        }

        return finalSize;
    }

    protected override Size MeasureOverride(Size constraint)
    {
        this.GenerateVisualChildren();
        this.GenerateListViewItemVisuals();
        // If it's coming back infinity, just return some value.
        if (constraint.Width == Double.PositiveInfinity)
            constraint.Width = 10;
        if (constraint.Height == Double.PositiveInfinity)
            constraint.Height = 10;

        return constraint;
    }

CalendarViewPeriodPersenter

protected override Size ArrangeOverride(Size finalSize)
{
    foreach (UIElement element in this.visualChildren)
    {
        element.Arrange(new Rect(new Point(0, 0), finalSize));
    }

     return finalSize;
}

protected override Size MeasureOverride(Size constraint)
{
      this.GenerateVisualChildren();
      return constraint;
}

RangePanel

    protected override Size ArrangeOverride(Size finalSize)
    {
        double containerRange = (this.Maximum - this.Minimum);

        foreach (UIElement element in this.Children)
        {
            double begin = (double)element.GetValue(RangePanel.BeginProperty);
            double end = (double)element.GetValue(RangePanel.EndProperty);
            double elementRange = end - begin;

            Size size = new Size();
            size.Width = (Orientation == Orientation.Vertical) ? finalSize.Width : elementRange / containerRange * finalSize.Width;
            size.Height = (Orientation == Orientation.Vertical) ? elementRange / containerRange * finalSize.Height : finalSize.Height;

            Point location = new Point();
            location.X = (Orientation == Orientation.Vertical) ? 0 : (begin - this.Minimum) / containerRange * finalSize.Width;
            location.Y = (Orientation == Orientation.Vertical) ? (begin - this.Minimum) / containerRange * finalSize.Height : 0;

            element.Arrange(new Rect(location, size));
        }

        return finalSize;
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        foreach (UIElement element in this.Children)
        {
            element.Measure(availableSize);
        }
        // Constrain infinities
        if (availableSize.Width == double.PositiveInfinity)
            availableSize.Width = 10;
        if (availableSize.Height == double.PositiveInfinity)
            availableSize.Height = 10;
        return availableSize;
    }

1 个答案:

答案 0 :(得分:1)

所以,今天早上经过多次打猎,我找到了一个解决方法。如果这提供了洞察力并且其他人找到了解决方案,我仍然会将您的标记视为已接受的解决方案,因为这对我来说似乎很苛刻。

基本上,今天早上,我拿出了众所周知的大棒,并决定看看如果我将MaxHeight设置为某个值(100)会发生什么,然后看看它会如何呈现。事实证明,它正确地控制了控制,并且看不到任何裁剪!所以,我想我会尝试将MaxHeight属性数据绑定到XAML中窗口的高度。这不起作用,所以我尝试从后面的代码中做到这一点,但仍然没有运气。所以,我回去验证这个现象,并再次将MaxHeight设置为100,并运行程序。它调整到窗口的大小,这是奇怪的,因为我没有把它设置为100?然后我意识到它将它设置为100,然后代码隐藏覆盖了该值,允许它向上扩展。调整窗口大小甚至具有所需的无剪裁效果......直到你达到100高度。所以,我将MaxHeight设置为零,这显然是在控件内部并打破了一些伪最小高度属性,然后窗口允许它扩展到它的全尺寸。

这是非常hacky,但它现在有效。 = /对我来说似乎很奇怪,我通过设置MaxHeight属性来启用缩小控件。 ><