Как я могу измерить элемент без введения побочных эффектов?
Как я могу попросить элемент управления вычислить его требования к минимальному размеру, но без какого-либо влияния на его текущее состояние или будущие макеты?
Например, скажем, у меня есть StackPanel в сетке. Ширина StackPanel будет растянута до размера ширины сетки. Но как я мог вычислить минимальную ширину StackPanels, не влияя ни на что.
Глядя на метод измерения, он говорит 'Updates the DesiredSize of a UIElement. Calling this method constitutes the first pass (the "Measure" pass) of a layout update.'
Так что у этого подхода есть побочные эффекты.
3 ответа
Я не верю, что это возможно сделать в WPF. Я хотел точно такую же способность (измерить, учитывая ограничение, не вызывая полного прохода измерения / аранжировки).
Один из экспериментов, которые я провел, состоял в том, чтобы сохранить текущий DesiredSize, затем InvalidateMeasure, затем UpdateLayout, а затем измерить и посмотреть на DesiredSize. Затем установите повторить это со старым / сохраненным размером. К сожалению, это медленно, и в нашем приложении есть побочный эффект, который заключается в том, что UpdateLayout() будет запускать цикл обработки событий для обработки событий макета. Это может привести к повторному входу и обработке других, не связанных событий в очереди, которые я не ожидал до тех пор, пока работа по измерению не была завершена. Хаос наступает. Короче говоря, это IMO дизайнерское решение (недостаток?) В WPF. Я открыл запрос UserVoice, ссылаясь на возможность измерения макетов без обработки событий. Я предсказываю, что этого никогда не произойдет.
Я прибег к использованию скрытого окна с экземпляром интересующего меня элемента управления без содержимого (например, с пустой кнопкой). Я делаю UpdateLayout, когда это безопасно, и беру желаемый размер как "пустой" размер. Я использую этот размер как часть расчетов позже. Я использую TextFormatter и GenericTextParagraphProperties для измерения текста так же, как TextBlock. Очень некрасивый код, чтобы избежать петли сообщений и оставить элементы управления без изменений! Это также хрупкое изменение шаблона b/c a, сделает мои вычисления недействительными. К счастью, я полностью контролирую шаблон для элементов управления, которые мне нужно измерить.
Я думаю, что лучшее, чего вы можете достичь, это вызвать метод Measure. У него есть побочные эффекты, но если вы вызываете его несколько раз, остается действительным только последнее состояние. Вам не нужно беспокоиться о визуальных артефактах, таких как мерцающие временные макеты. Только последний будет оказан.
Вы можете выполнить свой собственный расчет на основе кода, предоставленного Microsoft, например. StackPanel: http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/Stack.cs,9ef706576207e5a6,references
Однако StackPanel использует Measure своих дочерних элементов для вычисления своего собственного DesiredSize, поэтому может быть сложно вычислить это все самостоятельно. Я думаю, что вы должны предоставить больше информации, почему вы не хотите влиять на текущее состояние. Что не так с настройкой DesiredSize для UIElement?