Беда алгоритма макета WPF - размер элемента управления изменится, но не ниже некоторого произвольного значения - PullRequest
2 голосов
/ 15 апреля 2010

Я работаю над приложением для клиента, и одним из требований является возможность назначать встречи и отображать встречи на текущей неделе в визуальном формате, как в Календаре Google или Microsoft Office. Я нашел отличную (3 части) статью о проекте кода, в которой он строит «RangePanel» и составляет по одному для каждого «периода» (например, рабочего дня). Часть 1 можно найти здесь:

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

Код представлен, но, похоже, выбирает произвольное значение высоты в целом (440.04) и не будет изменять его размер без ограничения. Я хочу сказать, что размер окна / контейнера будет изменяться, но он просто обрезает нижнюю часть элемента управления вместо пересчета высоты панелей диапазона и элементов управления на панелях диапазона, представляющих назначение. Он изменит размеры и пересчитает для больших значений, но не меньше.

В отношении кода происходит следующее: когда вы изменяете размер ниже этого значения, сначала вызывается MeasureOverride с правильной «новой высотой». Однако к тому времени, когда вызывается метод ArrangeOverride, он передает то же значение 440.04, что и высота для размещения.

Мне нужно найти решение / обходной путь, но любая информация, которую вы можете предоставить, которая может направить меня на то, на что нужно обратить внимание, также будет принята с благодарностью (я понимаю, как сложно расстраивать код, когда у вас нет Кодовая база перед вами. :))

Код для различных функций Arrange и Measure приведен ниже. Элемент управления 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 Ответ

1 голос
/ 16 апреля 2010

Итак, после большой охоты этим утром я нашел обходной путь. Если это даст понимание, и кто-то другой найдет решение, я все равно буду отмечать ваше как принятое решение, потому что мне оно кажется таким хакерским.

По сути, этим утром я вытащил дубинку из пословиц и решил посмотреть, что произойдет, если установить для MaxHeight какое-то значение (100), и посмотреть, как он будет рендериться. Оказывается, он масштабировал управление должным образом, и в поле зрения не было никакого отсечения! Итак, я решил попробовать привязать свойство MaxHeight к высоте окна в XAML. Это не сработало, поэтому я попытался сделать это из кода, но мне все равно не повезло. Итак, я вернулся, чтобы проверить явление, и снова установил MaxHeight на 100, и запустил программу. Размер окна изменился до размера окна, что было странно, ведь я просто установил его на 100? Затем я понял, что он устанавливает его на 100, а затем кодовая область переопределяет это значение, позволяя увеличить его. Изменение размера окна даже дало желаемый эффект отсечения ... вплоть до 100 высоты. Итак, я установил MaxHeight на ноль, и это, очевидно, идет внутри элемента управления и нарушает некоторое свойство psuedo-минимальной высоты, а затем окно позволяет ему расширяться до его полного размера.

Это очень хакерский, но пока работает. = / Мне так странно, что я включил сжатие элемента управления, установив свойство MaxHeight. > <</p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...