RelativeSource - это расширение разметки, которое используется, в частности,
обязательные случаи, когда мы пытаемся связать свойство данного объекта с
другое свойство самого объекта, когда мы пытаемся связать свойство
объекта к другому из его родственников, при связывании
значение свойства зависимости для фрагмента XAML в случае пользовательского элемента управления
разработка и, наконец, в случае использования дифференциала ряда
связанные данные. Все эти ситуации выражены как относительный источник
режимы. Я разоблачу все эти случаи один за другим.
- Режим Self:
Представьте себе этот случай, прямоугольник, который мы хотим, чтобы его высота всегда
равна его ширине, скажем, квадрат. Мы можем сделать это с помощью
имя элемента
<Rectangle Fill="Red" Name="rectangle"
Height="100" Stroke="Black"
Canvas.Top="100" Canvas.Left="100"
Width="{Binding ElementName=rectangle,
Path=Height}"/>
Но в этом вышеупомянутом случае мы обязаны указать название
обязательный объект, а именно прямоугольник. Мы можем достичь той же цели
иначе используя RelativeSource
<Rectangle Fill="Red" Height="100"
Stroke="Black"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Height}"/>
В этом случае мы не обязаны указывать название обязательного
объект и ширина всегда будут равны высоте всякий раз, когда
высота изменилась.
Если вы хотите, чтобы параметр Width был равен половине высоты, тогда
Вы можете сделать это, добавив конвертер в расширение разметки Binding.
Давайте теперь представим другой случай:
<TextBlock Width="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualWidth}"/>
Приведенный выше случай используется для привязки данного свойства данного элемента к
один из его прямых родительских, так как этот элемент имеет свойство, которое
называется родитель Это приводит нас к другому режиму относительного источника, который
FindAncestor один.
- Режим FindAncestor
В этом случае свойство данного элемента будет привязано к одному из его
родители, Корс. Основным отличием от приведенного выше случая является то, что
что это зависит от вас, чтобы определить тип предка и предка
ранг в иерархии, чтобы связать свойство. Кстати попробуйте поиграть с
этот кусок XAML
<Canvas Name="Parent0">
<Border Name="Parent1"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualWidth}"
Height="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualHeight}">
<Canvas Name="Parent2">
<Border Name="Parent3"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualWidth}"
Height="{Binding RelativeSource={RelativeSource Self},
Path=Parent.ActualHeight}">
<Canvas Name="Parent4">
<TextBlock FontSize="16"
Margin="5" Text="Display the name of the ancestor"/>
<TextBlock FontSize="16"
Margin="50"
Text="{Binding RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type Border},
AncestorLevel=2},Path=Name}"
Width="200"/>
</Canvas>
</Border>
</Canvas>
</Border>
</Canvas>
Вышеуказанная ситуация имеет два встроенных элемента TextBlock
в пределах ряда границ и элементов холста, которые представляют их
иерархические родители. Второй текстовый блок будет отображать имя
данный родитель на относительном уровне источника.
Поэтому попробуйте изменить AncestorLevel = 2 на AncestorLevel = 1 и посмотрите, что
случается. Затем попробуйте изменить тип предка от
AncestorType = Border to AncestorType = Canvas и посмотрите, что происходит.
Отображаемый текст будет меняться в зависимости от типа предка и
уровень. Тогда что произойдет, если уровень предка не подходит для
тип предка? Это хороший вопрос, я знаю, что вы собираетесь
спроси это. Ответ без исключений будет брошен и ничто не будет
отображаться на уровне TextBlock.
- TemplatedParent
Этот режим позволяет привязать данное свойство ControlTemplate к свойству
элемента управления, к которому применяется ControlTemplate. Хорошо
понять проблему вот пример ниже
<Window.Resources>
<ControlTemplate x:Key="template">
<Canvas>
<Canvas.RenderTransform>
<RotateTransform Angle="20"/>
</Canvas.RenderTransform>
<Ellipse Height="100" Width="150"
Fill="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=Background}">
</Ellipse>
<ContentPresenter Margin="35"
Content="{Binding RelativeSource={RelativeSource
TemplatedParent},Path=Content}"/>
</Canvas>
</ControlTemplate>
</Window.Resources>
<Canvas Name="Parent0">
<Button Margin="50"
Template="{StaticResource template}" Height="0"
Canvas.Left="0" Canvas.Top="0" Width="0">
<TextBlock FontSize="22">Click me</TextBlock>
</Button>
</Canvas>
Если я хочу применить свойства данного элемента управления к его элементу управления
шаблон, то я могу использовать режим TemplatedParent. Также есть
похож на это расширение разметки, которое является TemplateBinding
что-то вроде короткой руки первого, но
TemplateBinding оценивается во время компиляции в отличие от
TemplatedParent, который оценивается сразу после первого запуска. Как
Вы можете заметить на рисунке ниже, фон и содержание
применяются изнутри кнопки к шаблону управления.