Wpf 附加属性

Wpf 附加属性,wpf,attached-properties,Wpf,Attached Properties,我对WPF附加属性有点困惑。使用附加属性时,该附加属性只能由定义它的类读取和使用,是否正确?例如,如果我想在按钮上使用某些附加属性作为悬停颜色,我可以从按钮的模板中获取附加属性值,并且我可以从按钮访问附加属性以设置胡佛颜色吗?您阅读了吗?如果没有,就去做 附加属性,比如,只需注册另一个可以在控件的属性字典中使用的键。您可以在任何地方设置值,也可以在任何地方检索值,它们不受类型限制。这意味着您可能只希望在按钮上设置,但也可以在文本框上设置 每个控件都有自己的属性键和值字典,附加的属性允许您使用新键

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

您阅读了吗?如果没有,就去做

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

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


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

使用示例添加到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>

除此之外,当父控件未定义某个属性(stackpanel未定义字体)时,附加属性对于使子控件具有某个属性(如在所有子控件上设置字体)非常有用。因此,即使这些属性是静态的,使用att.prop的每个UIElement。有一个实例,因为如果我在文本框和按钮上使用相同的属性,它们是否都有实例,我认为它是静态的。@mihajlv:只有属性字段是静态的,控件的值保存在每个控件的各个词典中。该字段仅注册用于该属性的密钥。密钥是什么意思?我知道键和字典的概念,但在这种情况下它代表什么?我认为我不必在按钮上注册属性,这样我就可以使用它,从概述中我得到的信息,我可以正确地使用它?@mihajlv:嗯,它更像是一个接口,实际上,字段是一个接口,允许您在控件的内部字典中设置值,它告诉系统“这是一个名为X的新属性,它可以包含Y“,然后您可以使用此接口在任何控件上设置该属性,该接口使用键X将值写入该控件的字典。在模板中,当您说SomeClass.HooverBrush时,它如何知道如何获取按钮设置的值,如果我有一个文本框也在设置SomeClass.HooverBrush,什么保持了这种关系?@mihajlv:代码在控件的delaration中,因此解析器在该控件的字典上设置值。这相当于在代码中调用
SomeClass.SetHoverBrush(控件问题)
。@H.B:所以在绑定中,它实际上是使用SomeClass的键访问该控件(模板化父控件)的字典。HooverBrush?@mihajlv:基本上,是的。这可能过于简单,因为我不知道所有的细节(还有字典,例如样式),所有答案几乎都是您需要的,所以我想添加我最喜欢的附加属性用法,称为。我们经常使用它们,因为我们可以将自定义逻辑“注入”到需要覆盖的控件中。因此,我们可以混合和组合附加行为,而无需仔细构造类层次结构。例如,自定义TreeViewService.AllowSelectOnRightClick就是附加行为的一个好例子。
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);
    }
}