子级属性会更新,称为父级的“ OnPropertyChanged” [英] Child properties update calling it's parent's `OnPropertyChanged`

查看:146
本文介绍了子级属性会更新,称为父级的“ OnPropertyChanged”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个XF组件,该组件的某些属性是从 BindableObject 继承的类型。为了说明,我使用了 Shadow 类,其中 double Radius Color ShadowColor 属性和类 MyBoxText ,它们具有 bool IsLoading Shadow Ghost 属性。



我的视图绑定正常工作,但是我的自定义渲染器存在问题:



当我更改 Ghost 属性时,需要重绘例如,整个视图( MyBoxText 控件的视图)。



这里是一些mcve:



类代码:

  public class MyBoxText:Label / *通过继承可绑定* / 
{
#region属性
public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(nameof(IsLoading),typeof(bool),typeof(MyBoxText),false);
public bool IsLoading
{
get {return(bool)GetValue(IsLoadingProperty); }
set {SetValue(IsLoadingProperty,value); }
}

公共静态只读BindableProperty GhostProperty = BindableProperty.Create(nameof(Ghost),typeof(Shadow),typeof(MyBoxText),null);
Public Shadow Ghost
{
get {return(Shadow)GetValue(GhostProperty); }
set {SetValue(GhostProperty,value); }
}
#endregion
}

public class Shadow:BindableObject / *显式可绑定* /
{
#region Properties
公共静态只读BindableProperty ShadowColorProperty = BindableProperty.Create(nameof(ShadowColor),typeof(Color),typeof(Shadow),Color.Black);
public Color ShadowColor
{
get {return(Color)GetValue(ShadowColorProperty); }
set {SetValue(ShadowColorProperty,value); }
}

public static readonly BindableProperty ShadowRadiusProperty = BindableProperty.Create(nameof(ShadowRadius),typeof(double),typeof(Shadow),20);
public double ShadowRadius
{
get {return(double)GetValue(ShadowRadiusProperty); }
set {SetValue(ShadowRadiusProperty,value); }
}
#endregion

public Shadow()
{

}
}

我的渲染器代码如下:

 公共类MyBoxText:LabelRenderer 
{
public MyBoxText()
{
SetWillNotDraw(false);
}

公共重写void Draw(Canvas canvas)
{
MyBoxText myView =(MyBoxText)this.Element;

//一些绘制逻辑
}

受保护的重写void OnElementPropertyChanged(object sender,PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(发送者,e);

if(e.PropertyName == MyBoxText.IsLoadingProperty.PropertyName ||
e.PropertyName == MyBoxText.GhostProperty.PropertyName)
Invalidate();
}
}

问题是,当我更改 Ghost.ShadowColor 属性不会调用我的'OnElementPropertyChanged'覆盖,并且视图在屏幕上仍保留旧颜色。



有没有一种方法可以将孩子的属性更新事件传播到父视图属性已更改,或者通过另一种方法来实现此目的?

解决方案

<问题是当我更改Ghost.ShadowColor属性时,不会调用我的'OnElementPropertyChanged'覆盖,并且视图在屏幕上保留旧颜色。
是否可以将孩子的属性更新事件传播到父视图属性已更改,或者通过另一种方法来实现此目的?


是的,有办法。由于您的Shadow继承自 BindableObject ,而后者实现了 INotifyPropertyChanged 接口。您可以设置通知 ShadowColor 更改:


  1. 添加 OnPropertyChanged()到Shadow.cs中的 ShadowColor 的设置器:

      public class Shadow:BindableObject / *显式可绑定* / 
    {
    #region属性
    public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create(nameof(ShadowColor) ,typeof(Color),typeof(Shadow),Color.Black);
    public Color ShadowColor
    {
    get {return(Color)GetValue(ShadowColorProperty); }
    set {SetValue(ShadowColorProperty,value);
    //通知ShadowColorProperty已更改
    OnPropertyChanged();
    }
    }
    ...
    }


  2. 像这样修改您的 MyBoxText.cs

      public class MyBoxText:Label / *通过继承可绑定* / 
    {
    ...

    public static readonly BindableProperty GhostProperty = BindableProperty.Create(nameof(Ghost),typeof(Shadow ),typeof(MyBoxText),null);
    Public Shadow Ghost
    {
    get {return(Shadow)GetValue(GhostProperty); }
    set {
    //注册ShadowColor更改事件
    的值。PropertyChanged+ = ShadowColor_PropertyChanged;
    SetValue(GhostProperty,value); }
    }

    private void ShadowColor_PropertyChanged(object sender,System.ComponentModel.PropertyChangedEventArgs e)
    {
    //注销事件
    this.Ghost。 PropertyChanged-= ShadowColor_PropertyChanged;
    //将this.Ghost设置为具有新ShadowColor的新对象,以触发OnPropertyChanged
    this.Ghost = new Shadow
    {
    ShadowColor =(发送者为Shadow)。ShadowColor,
    ShadowRadius = Ghost.ShadowRadius
    };
    }
    }



I'm trying to create a XF component whose some properties are of a type that inherits from BindableObject. For illustrating, I have class Shadow with double Radius and Color ShadowColor properties and a class MyBoxText, that have a bool IsLoading and a Shadow Ghost properties.

My View and it's Bindings is working as expected, but I have an issue with it's custom renderer:

When I change the Ghost properties I need to redraw the entire view (of the MyBoxText control), to visually update the shadow color, for example.

Here's some mcve:

Classes code:

public class MyBoxText : Label /* It's bindable by inheritance */
{
    #region Properties
    public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(nameof(IsLoading), typeof(bool), typeof(MyBoxText), false) ;
    public bool IsLoading
    {
        get { return (bool)GetValue(IsLoadingProperty); }
        set { SetValue(IsLoadingProperty, value); }
    }

    public static readonly BindableProperty GhostProperty = BindableProperty.Create(nameof(Ghost), typeof(Shadow), typeof(MyBoxText), null) ;
    public Shadow Ghost
    {
        get { return (Shadow)GetValue(GhostProperty); }
        set { SetValue(GhostProperty, value); }
    }
    #endregion
}

public class Shadow : BindableObject /* It's explictly bindable */
{
    #region Properties
    public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create(nameof(ShadowColor), typeof(Color), typeof(Shadow), Color.Black) ;
    public Color ShadowColor
    {
        get { return (Color)GetValue(ShadowColorProperty); }
        set { SetValue(ShadowColorProperty, value); }
    }

    public static readonly BindableProperty ShadowRadiusProperty = BindableProperty.Create(nameof(ShadowRadius), typeof(double), typeof(Shadow), 20) ;
    public double ShadowRadius
    {
        get { return (double)GetValue(ShadowRadiusProperty); }
        set { SetValue(ShadowRadiusProperty, value); }
    }
    #endregion

    public Shadow()
    {

    }
}

My renderer's code is like this:

public class MyBoxText : LabelRenderer
{
    public MyBoxText()
    {
        SetWillNotDraw(false);
    }

    public override void Draw(Canvas canvas)
    {
        MyBoxText myView = (MyBoxText)this.Element;

        // Some drawing logic
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName == MyBoxText.IsLoadingProperty.PropertyName  ||
            e.PropertyName == MyBoxText.GhostProperty.PropertyName )
            Invalidate();
    }
}

The issue is that when I change the Ghost.ShadowColor property my 'OnElementPropertyChanged' override is not called, and the View stays with the old color on the screen.

Is there a way to propagate the child's 'Property Update' event to parent view 'Property Changed' or another way to achieve this?

解决方案

The issue is that when I change the Ghost.ShadowColor property my 'OnElementPropertyChanged' override is not called, and the View stays with the old color on the screen. Is there a way to propagate the child's 'Property Update' event to parent view 'Property Changed' or another way to achieve this?

Yes, there is a way. Since your Shadow inherits from BindableObject, which implements the INotifyPropertyChanged Interface. You can set notify ShadowColor change:

  1. Add OnPropertyChanged() to Setter of ShadowColor in Shadow.cs:

    public class Shadow : BindableObject /* It's explictly bindable */
    {
        #region Properties
        public static readonly BindableProperty ShadowColorProperty = BindableProperty.Create(nameof(ShadowColor), typeof(Color), typeof(Shadow), Color.Black);
        public Color ShadowColor
        {
            get { return (Color)GetValue(ShadowColorProperty); }
            set { SetValue(ShadowColorProperty, value);
                //Notify the ShadowColorProperty Changed
                OnPropertyChanged();
            }
        }
       ...
    }
    

  2. Modify your MyBoxText.cs like this:

    public class MyBoxText : Label /* It's bindable by inheritance */
    {
     ...
    
        public static readonly BindableProperty GhostProperty = BindableProperty.Create(nameof(Ghost), typeof(Shadow), typeof(MyBoxText), null);
        public Shadow Ghost
        {
            get { return (Shadow)GetValue(GhostProperty); }
            set {
                //register the ShadowColor change event
                value.PropertyChanged += ShadowColor_PropertyChanged;
                SetValue(GhostProperty, value); }
        }
    
        private void ShadowColor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //unregister the event
            this.Ghost.PropertyChanged -= ShadowColor_PropertyChanged;
            //set this.Ghost to a new object with new ShadowColor to trigger the OnPropertyChanged
            this.Ghost = new Shadow
            {
                ShadowColor = (sender as Shadow).ShadowColor,
                ShadowRadius = Ghost.ShadowRadius
            };
        }
    }
    

这篇关于子级属性会更新,称为父级的“ OnPropertyChanged”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆