2011-04-02 66 views
3

我将一个附加行为添加到一个滑块,这会导致它在拇指被拖拽并保持在特定区域上时滚动某些内容。 (不能用一个简单的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被设置为真,这是全部在Slider的ControlTemplates.Triggers中完成,并能正常工作。

当其设置为true时,回调会将PreviewMouseEnterHandlers挂接到两个矩形中,以检测鼠标何时进入它们。

矩形的问题在滑块控件模板正是如此也被定义为:

 <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

做你ScrollLeftRect/ScrollRightRect永远不会设置? OutputWindow中是否存在绑定错误? – CodeNaked 2011-04-02 22:37:42

+0

使用断点时,它们始终显示为默认值。我得到了follwing绑定错误:System.Windows.Data错误:4:找不到与引用'ElementName = ScrollRightRect'绑定的源。 BindingExpression :(无路径);的DataItem = NULL;目标元素是'滑块'(Name ='MainSlider');目标属性是'ScrollRightRect'(键入'Rectangle')。我相信这是一个直截了当的错误。但我一直在考虑这个问题,只是无法发现它。 – rjw 2011-04-03 01:24:36

回答

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> 

该片段应引起“你好”时在按钮上我的鼠标出现了两次,但它没有,我也得到了同样的错误,你:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=theText'. BindingExpression:Path=Text; DataItem=null; target element is 'Button' (Name=''); target property is 'Content' (type '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。当您覆盖TextBoxit won't function until you add a control namedPART_ContentHost的模板时。

更新:我只是在博客这里模板部分:http://www.paulstovell.com/wpf-part-names