我正在添加一个附加的行为到一个滑块,这将导致它滚动一些内容时,拇指被拖动并保持在一个特定的区域。(不能使用直接的IsMouseOver触发器,因为滑块拇指有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,这都是在滑块的ControlTemplates.Triggers中完成的,并且工作正常。
当它设置为true时,回调将把PreviewMouseEnterHandlers挂钩到两个矩形中,以检测鼠标何时进入它们。
有问题的矩形也是在Slider的控件模板中定义的:
<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>我知道这个触发器被触发了,因为矩形像预期的那样填充了红色。有人能从这些片段中发现我做错了什么吗?
提前谢谢。
抢夺
发布于 2011-04-03 15:06:12
首先,让我们确认您没有做错任何事情,并且问题与附加的行为无关。
<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:Path=Text;名称;目标元素是‘DataItem=null’(名称=‘’);目标属性是'Content‘(类型为'Object')
这是可以解释的--一旦在Button上设置了绑定,它将无法找到名为“theText”的控件,因为该按钮位于不同的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。
更新:我刚刚在这里写了关于模板部件的博客:
https://stackoverflow.com/questions/5525062
复制相似问题