繁体   English   中英

属性设置器在XAML中不起作用

[英]Property setter not working in XAML

Canvas扩展了一个自定义控件,该控件只能接受Shape类的实例作为其子级。 考虑下面的代码:

public class SvgGroup : Canvas
{

    // ...

    public Brush Fill
    {
        // Retuns the fill brush value of all the shape children, if they are all the same. Otherwise, the default value of Brush is returned
        get
        {
            Brush rtn = default(Brush);
            for (int i = 0; i < ShapeChildren.Count; i++)
            {
                Shape shape = ShapeChildren[i];
                if (i == 0) // First loop
                {
                    rtn = shape.Fill;
                }
                else if (rtn != shape.Fill) // Children shapes have different Fill value
                {
                    return default(Brush);
                }
            }

            return rtn;
        }

        // Sets the fill brush value of all the shape children
        set
        {
            foreach (Shape shape in ShapeChildren)
            {
                shape.Fill = value;
            }
        }
    }

    // ...
}

问题是在XAML中设置Fill属性时,什么也没有发生。 但是,设置“在后台代码中填充”是可行的。

我当时在考虑依赖属性,但是这种情况下的实现可能会非常棘手。

我认为您应该定义两个依赖项属性,并且应该更新其中之一:

public class SvgGroup : Canvas
{

    public Brush Fill
    {
        get { return (Brush)GetValue(FillProperty); }
        set { SetValue(FillProperty, value); }
    }
    public static readonly DependencyProperty FillProperty
   = DependencyProperty.Register(
         "Fill",
         typeof(Brush),
         typeof(SvgGroup), 
         new FrameworkPropertyMetadata(Brushes.Red, OnFillPropertyChanged)
     );

    private static void OnFillPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SvgGroup svg = (SvgGroup)d;
        if (e.NewValue != null && !e.NewValue.Equals(e.OldValue))
        {
            foreach (Shape shape in d.ShapeChildren)
            {
                shape.Fill = (Brush)e.NewValue;
            }
            d.OnShapeBrushChanged(); // Note that you should call this method in some other places too.
        }
    }

    public Brush FillDifferentBrush
    {
        get { return (Brush)GetValue(IsFillDifferentProperty); }
    }

    public static readonly DependencyProperty FillDifferentProperty
        = DependencyProperty.Register(
              "FillDifferentBrush",
              typeof(Brush),
              typeof(SvgGroup),
              new PropertyMetadata(null)
          );




    void OnShapeBrushChanged()
    {
        Brush rtn = default(Brush);
        for (int i = 0; i < ShapeChildren.Count; i++)
        {
            Shape shape = ShapeChildren[i];
            if (i == 0) // First loop
            {
                rtn = shape.Fill;
            }
            else if (rtn != shape.Fill) // Children shapes have different Fill value
            {
                SetValue(FillDifferentProperty, default(Brush));
            }
            else
                SetValue(FillDifferentProperty, rtn);
        }
    }

}

您应该正确调用OnShapeBrushChanged() (例如,当添加新的OnShapeBrushChanged()或单独更改其Brush或调用Fill属性时),以使其保持更新状态(类似于ItemsControl的HasItems属性)。

您可以声明具有属性值继承行为的附加属性

在任何父元素上设置属性后,其值将被所有子元素继承。 有一个PropertyChanged回调,它检查元素是否为Shape并最终将继承的Brush应用于Shape的Fill属性。

public static class ChildFillEx
{
    public static readonly DependencyProperty ChildFillProperty =
        DependencyProperty.RegisterAttached(
            "ChildFill", typeof(Brush), typeof(ChildFillEx),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.Inherits,
                ChildFillPropertyChanged));

    public static Brush GetChildFill(DependencyObject obj)
    {
        return (Brush)obj.GetValue(ChildFillProperty);
    }

    public static void SetChildFill(DependencyObject obj, Brush value)
    {
        obj.SetValue(ChildFillProperty, value);
    }

    private static void ChildFillPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var shape = obj as Shape;
        if (shape != null)
        {
            shape.Fill = (Brush)e.NewValue;
        }
    }
}

您可以这样使用它:

<Canvas local:ChildFillEx.ChildFill="Red">
    <Rectangle Width="100" Height="100" />
</Canvas>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM