我正在向滑块添加附加行为,这会导致当拖动拇指并将其保持在特定区域时滚动某些内容。 (不能使用简单的IsMouseOver触发器,因为Slider Thumb具有MouseCapture。)
该行为有3个属性:
#region IsScrollHoverProperty
public static readonly DependencyProperty IsScrollHoverProperty = DependencyProperty.RegisterAttached(
"IsScrollHover",
typeof(Boolean),
typeof(ScrollHoverAreaBehaviour),
new UIPropertyMetadata(false));
#endregion
#region ScrollLeftRectProperty
public static readonly DependencyProperty ScrollLeftRectProperty = DependencyProperty.RegisterAttached(
"ScrollLeftRect",
typeof(Rectangle),
typeof(ScrollHoverAreaBehaviour),
new UIPropertyMetadata(null));
#endregion
#region ScrollRightRectProperty
public static readonly DependencyProperty ScrollRightRectProperty = DependencyProperty.RegisterAttached(
"ScrollRightRect",
typeof(Rectangle),
typeof(ScrollHoverAreaBehaviour),
new UIPropertyMetadata(null));
#endregion
当用户拖动滑块时,IsScrollHoverProperty被设置为true,这一切都在Slider的ControlTemplates.Triggers中完成,并且工作正常。
当它设置为true时,回调将把PreviewMouseEnterHandlers挂钩到两个Rectangle中以检测鼠标何时进入它们。
有问题的矩形也在Slider的controltemplate中定义:
<StackPanel Grid.Row="0" Grid.RowSpan="3" HorizontalAlignment="Left" Orientation="Horizontal">
<Rectangle Width="40" Fill="#AAAAAAAA" Name="ScrollLeftRect"/>
</StackPanel>
<StackPanel Grid.Row="0" Grid.RowSpan="3" HorizontalAlignment="Right" Orientation="Horizontal">
<Rectangle Width="40" Fill="#AAAAAAAA" Name="ScrollRightRect"/>
</StackPanel>
我遇到的问题是将这些矩形绑定到附加的ScrollRightRect和ScrollLeftRect属性。我尝试了一些事情,并怀疑我犯了一个愚蠢的绑定错误,或者我试图做一些不允许的事情。我目前正在controltemplate.triggers中绑定它们,如下所示:
<Trigger Property="local:ScrollHoverAreaBehaviour.IsScrollHover" Value="False">
<Setter Property="local:ScrollHoverAreaBehaviour.ScrollLeftRect" Value="{Binding ElementName=ScrollLeftRect}"/>
<Setter Property="local:ScrollHoverAreaBehaviour.ScrollRightRect" Value="{Binding ElementName=ScrollRightRect}"/>
<Setter TargetName="ScrollLeftRect" Property="Fill" Value="Red"/>
<Setter TargetName="ScrollRightRect" Property="Fill" Value="Red"/>
</Trigger>
我知道这个触发器正在跳闸,因为矩形按预期填充红色。 谁能从这些片段中发现我做错了什么?
提前致谢。
罗布
答案 0 :(得分:13)
首先,让我们确认你没有做错任何事,这个问题与附加的行为无关。
<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>
当我将鼠标悬停在按钮上时,此代码段会导致“Hello”出现两次,但它没有,并且我得到与您相同的错误:
System.Windows.Data错误:4:无法找到引用'ElementName = theText'的绑定源。 BindingExpression:路径=文本;的DataItem = NULL; target元素是'Button'(Name =''); target属性是'Content'(类型'Object')
这是可以解释的 - 一旦在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
,it won't function until you add a control named PART_ContentHost
。
更新:我刚刚在此处发布了有关模板部分的博文:http://www.paulstovell.com/wpf-part-names