【问题标题】:Attached Properties附加属性
【发布时间】:2011-11-01 05:07:12
【问题描述】:

我对 WPF 附加属性有点困惑。当您使用附加属性时,该附加属性只能由定义它的类读取和使用,对吗?例如,如果我想在按钮上使用一些附加属性作为悬停颜色,我可以从按钮的模板中获取附加属性值,并且我可以从按钮访问附加属性来设置悬停颜色吗?

【问题讨论】:

  • 所有答案几乎就是您需要的一切,所以我想添加我最喜欢的附加属性用法,称为attached behaviors。我们经常使用它们,因为我们可以将自定义逻辑“注入”到我们需要覆盖的控件中。因此,我们可以混合和组合附加的行为,而无需仔细构建类层次结构。例如,自定义 TreeViewService.AllowSelectOnRightClick 就是附加行为的一个很好的例子。

标签: wpf attached-properties


【解决方案1】:

补充 H.B. 的答案。举个例子:

例如,如果我想使用一些附加属性作为悬停 按钮上的颜色,我可以从 按钮的模板,我能否访问附加的属性 从按钮设置悬停颜色?

是的,你当然可以。假设您在名为 SomeClass 的类中定义了一个名为 HoverBrush 的附加属性,您可以在实例上设置值并在模板中绑定到它

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
            <Border x:Name="border" Background="Gray">
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="border"
                            Property="Background"
                            Value="{Binding RelativeSource={RelativeSource TemplatedParent},
                                            Path=(local:SomeClass.HoverBrush)}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </StackPanel.Resources>
    <Button Content="Blue Hover"
            local:SomeClass.HoverBrush="Blue"
            Template="{StaticResource MyButtonTemplate}"/>
    <Button Content="Green Hover"
            local:SomeClass.HoverBrush="Green"
            Template="{StaticResource MyButtonTemplate}"/>
</StackPanel>

相关的附加属性是这样定义的

public class SomeClass
{
    public static DependencyProperty HoverBrushProperty =
        DependencyProperty.RegisterAttached("HoverBrush",
                                            typeof(Brush),
                                            typeof(SomeClass),
                                            new PropertyMetadata(null));
    public static void SetHoverBrush(DependencyObject obj, Brush value)
    {
        obj.SetValue(HoverBrushProperty, value);
    }
    public static Brush GetHoverBrush(DependencyObject obj)
    {
        return (Brush)obj.GetValue(HoverBrushProperty);
    }
}

【讨论】:

  • 在模板中当你说 SomeClass.HooverBrush 它怎么知道获取按钮设置的值,如果我有一个文本框也设置 SomeClass.HooverBrush,什么保持关系?
  • @mihajlv:代码在控件的声明中,因此解析器在该控件的字典中设置值。这相当于在代码中调用SomeClass.SetHoverBrush(TheControlInQuestion)
  • @H.B.:所以在绑定内部,它实际上是使用 SomeClass.HooverBrush 的键访问该控件(模板化父级)的字典?
  • @mihajlv:基本上,是的。这可能过于简单化了,因为我不知道所有细节(也有字典at several levels,例如样式)
  • SomeClass 应该是静态的。
【解决方案2】:

你读过the overview吗?如果没有,那就去做吧。

附加属性,如dependency properties,只需注册另一个可以在控件属性字典中使用的键。您可以在任何地方设置值,也可以在任何地方检索它们,它们不受类型限制。这意味着您可能只希望在 Buttons 上设置它,但也可以在 TextBoxes 上设置它。

每个控件都有自己的属性键和值字典,附加属性允许您使用新键将值写入这些字典。由于这些字典是独立的,因此它们可以为通过静态字段属性声明设置和访问的同一属性具有不同的值。

由于附加了这些属性,您必须通过 GetValue 获取值(因为这些类本身不能提供 CLR 包装器)。

【讨论】:

  • 除此之外,当父控件没有定义该属性(堆栈面板没有' t 定义字体)。
  • 所以即使它们是静态的,每个使用 att.prop 的 UIElement。有一个实例,因为如果我在文本框和按钮上使用相同的属性,它们每个都有一个实例,我认为它是静态的。
  • @mihajlv:只有属性字段是静态的,控件的值保存在每个控件的单独字典中。该字段仅注册用于该属性的键。
  • key是什么意思?我知道键和字典的概念,但在这种情况下它代表什么?我认为我不必在按钮上注册属性以便我可以使用它,根据我从概述中得到的信息,我可以正确使用它吗?
  • @mihajlv:嗯,实际上它更像是一个接口,该字段是允许您在控件的内部字典中设置值的接口,它告诉系统“这是一个新属性,它是称为 X 并且可以包含 Y”,然后您可以使用此接口在任何控件上设置该属性,该接口使用键 X 将值写入该控件的字典。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多