Привязка к ActualHeight не работает

Я попытался создать собственный элемент управления с полупрозрачным закругленным фоном:

<Canvas>
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               Width="{Binding Source=StopText, Path=ActualHeight}" 
               Height="20"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>

Проблема в том, что я, наверное, не могу привязаться к свойствам ActualHeight/ActualWidth, потому что они не являются зависимыми.

Что делать, чтобы прямоугольник и текстовое поле были одинакового размера?


person serhio    schedule 24.09.2010    source источник


Ответы (1)


Правильная привязка заключается в использовании ElementName, а не Source при привязке к другому элементу:

<Canvas>
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               Width="{Binding ElementName=StopText, Path=ActualHeight}" 
               Height="20"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>

Кроме того, вы понимаете, что привязываете ширину Rectangle к Height TextBlock, верно?

Если это действительно то, как вы хотите настроить свой элемент управления, вам нужно привязать ширину Rectangle к ActualWidth TextBlock, а Height к ActualHeight.

ОБНОВЛЕНИЕ Согласно комментариям ниже, вот реализация, использующая Grid без привязки:

<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <TextBlock x:Name="StopText" Text="Some test text"/>
    <Rectangle Fill="SkyBlue"
               HorizontalAlignment="Stretch"
               VerticalAlignment="Stretch"  
               RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Grid>

Grid и Canvas используют разные системы компоновки, и, поскольку вы не используете функции, предоставляемые Canvas, Grid это лучший выбор.

Большая разница в дочерних элементах заключается в том, что Rectangle теперь просто использует Horizontal и VerticalAlignment до Stretch для всего Grid, вместо того, чтобы беспокоиться о размерах чего-либо.

person Wonko the Sane    schedule 24.09.2010
comment
Хорошее наблюдение по поводу ElementName. Что делать, если я хочу привязать его к самому холсту (основному элементу UserControl). Что я должен установить? - person serhio; 24.09.2010
comment
Я бы просто использовал сетку вместо холста, и тогда вам вообще не нужна привязка. Я обновлю свой ответ. - person Wonko the Sane; 24.09.2010
comment
Хм... С Canvas я использовал this.SetValue(Canvas.LeftProperty для установки местоположения UserControl (внутри UserControl). Как я могу теперь поступить с Решеткой? - person serhio; 24.09.2010
comment
Я даже считаю, что должен быть способ стилизовать TextBox, чтобы не нужен внешний фоновый прямоугольник... - person serhio; 24.09.2010
comment
#1.) Вы все еще можете установить Canvas.LeftProperty, даже если это Grid. #2.) Да, вы, безусловно, можете стилизовать TextBlock (или TextBox, или любой UIElement), настроив ControlTemplate, используя свойство Template этого UIElement. Это (?) фундаментальная основа WPF. - person Wonko the Sane; 24.09.2010
comment
№1). Я проверял, и, к сожалению, это не работает, поэтому я сбросил Canvas как было... - person serhio; 24.09.2010
comment
Моя ошибка. Тем не менее, вы могли бы получить тот же эффект, указав поле. element.Margin = новая толщина (50d, 5d, 5d, 5d); - person Wonko the Sane; 24.09.2010