WPF附加属性在XAML中设置时未触发代码后台。

4
我有一个自定义的ClockFace UserControl,其中具有允许更改颜色、字体和指针(作为Path对象)的属性。这在自定义的TimePicker和Clock UserControls中使用。在这些父控件中,可以很好地在xaml中设置ClockFace属性。 我想要做的是公开这些ClockFace属性,以便它们可以在这两个父控件上设置(例如,Clock和TimePicker对象)。我认为将它们变成附加属性就可以解决问题,因此我尝试了其中一个颜色属性。
public static readonly DependencyProperty HourTicksBrushProperty = DependencyProperty.RegisterAttached("HourTicksBrush", typeof(Brush), typeof(ClockFace), new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetHourTicksBrush(DependencyObject element, Brush value)
{
    element.SetValue(HourTicksBrushProperty, value);
}
public static Brush GetHourTicksBrush(DependencyObject element)
{
    return (Brush)element.GetValue(HourTicksBrushProperty);
}

我可以在包含时钟的 XAML 中使用此附加属性:(Controls 是 XML 命名空间)
<Controls:Clock Controls:ClockFace.HourTicksBrush="Aqua" />

它可以正常编译,但是尽管附加的HourTicksBrushProperty默认值(Brushes.Black)显示出来了,但在父级Clock控件(Aqua)上设置的值从未触发上述方法或更改颜色。我有什么遗漏吗?
明确一点,我想能够在父控件上使用上述XAML来设置子ClockFace控件的HourTicksBrush属性。
非常感谢您的任何帮助。
2个回答

6
你附加属性类中的“get”和“set”方法实际上只是为了方便你自己的代码。XAML解析器会忽略这些方法,直接调用element.SetValue。如果你想要响应setter,你需要在FrameworkPropertyMetadata中提供一个属性更改处理程序。
public static readonly DependencyProperty HourTicksBrushProperty = DependencyProperty.RegisterAttached(
    "HourTicksBrush", 
    typeof(Brush), 
    typeof(ClockFace), 
    new FrameworkPropertyMetadata(
        Brushes.Black, 
        FrameworkPropertyMetadataOptions.AffectsRender,
        HourTicksBrushChanged));

public static void SetHourTicksBrush(DependencyObject element, Brush value)
{
    element.SetValue(HourTicksBrushProperty, value); //not always called
}
public static Brush GetHourTicksBrush(DependencyObject element)
{
    return (Brush)element.GetValue(HourTicksBrushProperty); //not always called
}
private static void HourTicksBrushChanged(DependencyObject sender, somethingsomethingArgs args){
    // do stuff with sender and args.NewValue here
}

很抱歉我的问题中省略了我想在代码后台捕获传入的值这一事实,对此给大家带来了困扰。特别感谢Rob猜到了我的意图。非常感谢Rob。 - Sheridan
我之前也遇到了同样的问题,所以猜测起来很容易 :) - Rob Fonseca-Ensor
想知道为什么互联网博客中几乎所有的附加属性和行为示例中都会出现SetXXX和GetXXX。 - Elaine
根据 https://stackoverflow.com/questions/31701336/ (我想是这个?),somethingsomethingArgs 等同于 DependencyPropertyChangedEventArgs - Ben

0

可以使用类似以下的语法:

public static readonly DependencyProperty HourTicksBrushProperty = DependencyProperty.RegisterAttached("HourTicksBrush", typeof(Brush), typeof(ClockFace), new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender));


public static Brush HourTicksBrush
{
    get { return (Brush)GetValue(HourTicksBrushProperty); }
    set { SetValue(HourTicksBrushProperty); }
}

在XAML中类似于这样的东西

<Controls:Clockface.HourTicks Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HourTicksBrush}/>

我不确定在RelativeSource中是使用TemplatedParent还是Self。


我可能解释不清楚。我已经更新了我使用的XAML。我的XAML没有问题...只是设置值不会触发ClockFace中的SetHourTicksBrush方法,因此不会更新Brush。 - Sheridan
但是为什么在父控件上设置Brush属性时它不更新,而在实际的ClockFace控件上设置时却会更新呢?或者稍微改变一下问题...我该如何实现这个功能? - Sheridan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接