首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >绑定到控件模板中元素的附加行为

绑定到控件模板中元素的附加行为
EN

Stack Overflow用户
提问于 2011-04-03 02:30:56
回答 1查看 5.4K关注 0票数 3

我正在添加一个附加的行为到一个滑块,这将导致它滚动一些内容时,拇指被拖动并保持在一个特定的区域。(不能使用直接的IsMouseOver触发器,因为滑块拇指有MouseCapture。)

该行为有3个属性:

代码语言:javascript
复制
    #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的控件模板中定义的:

代码语言:javascript
复制
        <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中绑定它们,如下所示:

代码语言:javascript
复制
        <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>

我知道这个触发器被触发了,因为矩形像预期的那样填充了红色。有人能从这些片段中发现我做错了什么吗?

提前谢谢。

抢夺

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-04-03 15:06:12

首先,让我们确认您没有做错任何事情,并且问题与附加的行为无关。

代码语言:javascript
复制
<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_“前缀:

代码语言:javascript
复制
<Rectangle ... Name="PART_ScrollLeftRect" />

现在,在设置IsScrollHover时,将如下代码放入回调中:

代码语言:javascript
复制
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

更新:我刚刚在这里写了关于模板部件的博客:

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5525062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档