WPF: общий размер на пользовательской панели?

Я пытаюсь реализовать что-то похожее на SharedSizeGroup в Column/RowDefinition для Grids.

Упрощенный случай:

<l:MyCustomPanel>
  <l:MyCustomPanel>
    <TextBlock l:MyCustomPanel.SharedWidth="t1" />
  </l:MyCustomPanel>
  <l:MyCustomPanel>
    <TextBlock l:MyCustomPanel.SharedWidth="t1" />
  </l:MyCustomPanel>
</l:MyCustomPanel>

Корневая панель определяет область действия. Все элементы с одинаковым SharedWidth должны иметь одинаковую ширину. Я реализовал свое собственное поведение Measure и Arrange, но я изо всех сил пытаюсь заставить его работать с моделью SharedSize. Я подозреваю, что мне нужно как-то сделать два прохода процесса аранжировки? Сначала один, чтобы узнать размеры по умолчанию (и собрать максимальную ширину), а затем еще один проход, чтобы использовать эту максимальную ширину в качестве параметра в результате аранжировки. Но как мне это сделать? Я думаю, я не могу выполнить два прохода в каждом ArrangeOverride, потому что это приведет к тому, что каждый элемент будет делать два прохода всего своего дерева нисходящих элементов? Хммммм. Какие-либо предложения?

ОБНОВЛЕНИЕ

Этот код иллюстрирует проблему более подробно:

public class CustomPanel : Panel
{
    protected override Size MeasureOverride(Size availableSize)
    {
        Children[0].Measure(availableSize);
        return Children[0].DesiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        Children[0].Arrange(new Rect(new Point(), new Size(finalSize.Width / 2, finalSize.Height)));
        return finalSize;
    }
}

<StackPanel>
  <l:CustomPanel>
    <TextBox />
  </l:CustomPanel>
</StackPanel>

При вводе текста в текстовое поле оно переполняется, а пространство становится недоступным...


person Andreas Zita    schedule 20.04.2011    source источник


Ответы (1)


Как назло, эти два прохода всего дерева уже встроены в систему компоновки. Сначала соберите все натуральные размеры во время MeasureOverride прохода, а затем используйте эту информацию во время ArrangeOverride прохода для выбора общих значений ширины.

person Rick Sladkey    schedule 21.04.2011
comment
Аааа я вижу. Но поскольку доступное пространство, переданное в Measure для каждого дочернего элемента, изменяется в Arrange (когда доступны собранные максимальные значения), кажется, что элементы по-прежнему ведут себя так, как если бы у них было все то пространство, которое им было дано изначально, но обрезано. Например, текстовые поля расширяются за пределы прямоугольника расположения, как если бы у них было больше места для расширения. Как это можно решить? - person Andreas Zita; 21.04.2011
comment
Во время прохода упорядочивания вы знаете как желаемую ширину текстового блока, так и вычисленную общую ширину текстового блока, которая должна быть больше. Вы отвечаете за это: просто установите последний прямоугольник текстового блока, чтобы включить общую ширину, и текстовый блок будет соответствовать. - person Rick Sladkey; 21.04.2011
comment
Текстовое поле не соответствует моему коду, но я, вероятно, делаю что-то не так... Я обновил этот пост некоторым кодом. - person Andreas Zita; 22.04.2011
comment
Во-первых, вы должны помнить, что каждый раз, когда вы вводите символ в текстовое поле, это приводит к еще одной паре проходов измерения и аранжировки. Во-вторых, если окончательный размер, который вы назначаете ему во время аранжировки, меньше желаемого размера во время такта, он будет обрезан. В этом случае вам нужно принудительно создать новый макет с помощью UpdateLayout, на этот раз указав меньший доступный размер во время измерения. - person Rick Sladkey; 22.04.2011
comment
Итак, чтобы создать общее поведение размера, мне нужно было бы выполнить два прохода измерения (измерение-›расстановка-›измерение-›расстановка)? Плохо то, что окончательный размер, указанный в аранжировке, используется не более чем для рендеринга. - person Andreas Zita; 25.04.2011