В чем разница между шириной и фактической шириной в WPF?

В настоящее время я работаю с Panels в WPF и заметил, что в отношении свойств Width и Height есть также два других свойства, называемых ActualWidth и ActualHeight.

ActualWidth

Получает отображаемую ширину этого элемента. Это свойство зависимости. (Унаследовано от FrameworkElement.)

Width

Получает или задает ширину элемента. Это свойство зависимости. (Унаследовано от FrameworkElement.)

Ссылка: MSDN

Может ли кто-нибудь указать различия между ними и когда использовать любой из них?


person Andreas Grech    schedule 03.03.2009    source источник


Ответы (7)


Width/Height – это запрошенный размер макета. Если вы установите значение Auto, то значение будет double.NaN при доступе к свойству в коде позади.

ActualWidth/ActualHeight и RenderSize.Width/RenderSize.Height возвращают отображаемый размер элемента, поскольку RenderSize имеет тип Size. Если вам нужен/нужен фактический размер элемента, используйте любой из этих атрибутов.

person Muad'Dib    schedule 03.03.2009
comment
На самом деле это размер макета, а не отображаемый размер. - person chuckj; 04.03.2009
comment
@chuckj, какой атрибут можно использовать для получения отображаемого размера? - person dumbledad; 05.07.2015
comment
@дамблдад .RenderSize.Width - person Mafii; 12.07.2016

Я нахожу ActualWidth наиболее полезным, когда хочу привязать ширину или высоту одного элемента к другому.

В этом простом примере у меня есть две кнопки, расположенные рядом, и комментарий под ним, который ограничен шириной StackPanel, содержащей две кнопки.

<StackPanel>

    <StackPanel Margin="0,12,0,0" Orientation="Horizontal" Name="buttonPanel" HorizontalAlignment="Left" >
         <Button Content="Yes - Arm the missile" FontWeight="Bold" HorizontalAlignment="Left"/>
         <Button Content="No - Save the world" HorizontalAlignment="Left" Margin="7,0,0,0"/>
    </StackPanel>

    <TextBlock Text="Please choose whether you want to arm the missile and kill everybody, or save the world by deactivating the missile." 
               Width="{Binding Path=ActualWidth,ElementName=buttonPanel}" Margin="0,5,0,0" HorizontalAlignment="Left" TextWrapping="Wrap"/>

</StackPanel>
person Simon_Weaver    schedule 25.10.2010

ActualWidth учитывает заполнение значения, поэтому в любое время, когда вам нужно узнать это число, вы можете вызвать Actualwidth вместо ширины и избежать вычислений.

редактировать: удален Margin, потому что он не является частью ActualWidth.

person TWood    schedule 21.10.2010

Есть очень веская причина не использовать ActualWidth для привязки (очевидно, ActualHeight соответственно). Когда вы устанавливаете Width элемента на ActualWidth другого, вы можете разорвать цепочку макетов.

В лучшем случае ваш элемент/элемент управления необходимо проанализировать после завершения процесса макета родителя (источника привязки). Это означает дополнительное время. Если он находится на том же уровне иерархии, что и родительский, процесс компоновки требует двух прогонов (как минимум) для расчета окончательного размера.

Например, у меня был элемент управления, свойство размера которого было переопределено в стиле, который установил бы для него значение TemplatedParent (не делать):

<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding ActualWidth}" 
           Height="1" Fill="#000000"/>

При изменении размера содержащего окна элемент управления предотвратит уменьшение размера контейнера и нарушит макет. Установка значения Width решит проблему (сделать):

<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding Width}" 
           Height="1" Fill="#000000"/>

Если вам приходится использовать ActualWidth в общем, что-то не так с вашим xaml. Лучше исправить это, чем портить окончательные размеры макета.

person Pascal    schedule 04.10.2013
comment
Ваши фрагменты кода (не делайте и не делайте) абсолютно одинаковы?!?! - person PIntag; 19.08.2014
comment
Спасибо за комментарий. Исправлено. - person Pascal; 20.08.2014
comment
@tuner Я не согласен с этим: если вам приходится использовать ActualWidth в целом, что-то не так с вашим xaml. В привязке к ActualWidth (или ActualHeight) нет ничего плохого, ведь в некоторых случаях это может быть самым простым способом решения конкретной проблемы макета. Тот факт, что привязка к этим свойствам вызывает проблемы в (редких) случаях, не является причиной, чтобы полностью их избегать. - person Steven Rands; 06.02.2015
comment
@StevenRands: проблема с вашими редкими случаями заключается в том, что очень сложно найти источник проблемы. Если вы привязываете свойства, определяющие размер компонента, к ActualWidth или аналогичному, для определения размера компонента необходимо как минимум два прохода компоновки. Мой личный опыт показывает, что сначала это работает. Затем, после введения другого нестандартного поведения (которым оно и является), все ломается, и у вас возникают реальные проблемы с его фиксацией. - person Pascal; 06.02.2015
comment
@tuner Я использовал эту технику довольно много раз, и у меня никогда не было проблем, о которых вы упоминаете. Может быть, мне просто повезло. Есть места, где я бы не стал его использовать, но я думаю, что общее утверждение, которое в основном говорит, что используйте это, и вы делаете это неправильно, бесполезно. Я понимаю вашу точку зрения о множественных проходах макета, но я думаю, что такой тип привязки часто является самым простым способом сказать в XAML: я хочу, чтобы элемент this имел ту же ширину (или высоту), что и этот элемент. Во всяком случае, просто мнение. - person Steven Rands; 06.02.2015
comment
@Pascal: у меня есть поведение, требующее ввести команду меню, чтобы перерисовать мой экран, чтобы ActualHeight не был равен 0. Итак, в коде я жестко запрограммировал высоту до тех пор, пока элемент управления не сделает ее доступной. Почему это? И как избежать? Я не вижу, где установить или убрать Auto on Label control. - person J W; 14.12.2020
comment
@JW: Вы можете заглянуть в свой элемент управления, если он вообще запрашивает размер. Если другие элементы управления настроены на увеличение, а ваш конкретный элемент управления не запрашивает минимальный размер, он будет уменьшен до нуля, пока это не будет изменено. - person Pascal; 02.01.2021

ActualWidth устанавливается системой рендеринга и может отличаться в зависимости от ширины других элементов и общих ограничений размера. В результате его нельзя изменить. Width — это свойство, которое можно изменить, и его следует использовать для увеличения или уменьшения ширины элемента.

Из MSDN:

Это свойство является вычисляемым значением, основанным на других входных данных ширины и системе макета. Значение устанавливается самой системой компоновки на основе фактического прохода рендеринга и поэтому может немного отставать от установленного значения таких свойств, как Width, которые являются основой изменения ввода.

person Andy Mikula    schedule 03.03.2009

Это именно то, что ширина рендера! = ширина макета. Один предназначен для макета, другой — для рендеринга. Как и в случае с WinForms, есть свойство Size и ClientSize, они немного отличаются, и вы должны использовать размер Atual/Client для рендеринга и ширину/высоту для макета.

person John Leidegren    schedule 03.03.2009

Вы можете установить свойство Width, но не свойство ActualWidth.

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

ActualWidth не устанавливается сразу при установке свойства Width, но будет обновляться (один или несколько раз) во время рендеринга.

person Guffa    schedule 03.03.2009