Во-первых, давайте подтвердим, что вы не делаете ничего плохого, и проблема не имеет ничего общего с прикрепленным поведением.
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="Yellow">
<StackPanel>
<TextBlock x:Name="theText" Text="Hello" />
<ContentPresenter />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content" Value="{Binding ElementName=theText, Path=Text}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
Этот фрагмент должен вызывать появление «Привет» дважды, когда я наводю курсор мыши на кнопку, но это не так, и я получаю ту же ошибку, что и вы:
System.Windows.Data Ошибка: 4: не удается найти источник для привязки со ссылкой «ElementName = theText». BindingExpression: Path = Text; DataItem = NULL; Целевым элементом является «Кнопка» (Имя = ''); Целевым свойством является «Содержимое» (тип «Объект»)
Это объяснимо - после того, как привязка установлена на Button
, он не сможет найти элемент управления с именем 'theText', потому что Button находится в другом NameScope .
Альтернатива
Некоторые элементы управления WPF должны делать что-то похожее на вас - они предполагают, что в дереве существует определенный элемент управления, с которым они будут взаимодействовать. Но они не используют свойства - они используют имена.
Начните с того, что дайте элементам управления имя - принято использовать префикс "PART_":
<Rectangle ... Name="PART_ScrollLeftRect" />
Теперь добавьте такой код в ваш обратный вызов, когда установлено IsScrollHover
:
private static void IsScrollHoverSetCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (Slider) d;
if ((bool)e.NewValue == false)
return;
target.ApplyTemplate();
var leftRectangle = target.Template.FindName("PART_ScrollLeftRect", target);
var rightRectangle = target.Template.FindName("PART_ScrollRightRect", target);
// Do things with the rectangles
}
Обратите внимание, что в зависимости от того, когда установлено свойство IsScrollHost
, шаблон может быть еще не готов. В этом случае вы можете подписаться на Loaded
или подобное событие, а затем позвонить ApplyTemplate()
.
Хотя это может показаться более сложным, у него есть одно приятное преимущество: разметка будет проще. Дизайнеру, использующему Blend, не нужно будет забывать подключать эти сложные триггеры, он просто должен правильно называть элементы управления.
Использование префикса PART_ является соглашением WPF и обычно используется вместе с атрибутом TemplatePart . Примером этого является TextBox. При переопределении шаблона TextBox
, он не будет работать, пока вы не добавите элемент управления с именем PART_ContentHost
.
Обновление: я только что написал о деталях шаблона здесь: http://www.paulstovell.com/wpf-part-names