c# - 子属性更新调用它的父属性 `OnPropertyChanged`

标签 c# xamarin binding xamarin.android custom-controls

我正在尝试创建一个 XF 组件,其某些属性属于从 BindableObject 继承的类型。为了说明,我有类 Shadowdouble RadiusColor ShadowColor 属性和类 MyBoxText,有一个bool IsLoading 和一个 Shadow Ghost 属性。

我的 View 和它的 Bindings 按预期工作,但我的自定义渲染器有问题:

当我更改 Ghost 属性时,我需要重绘整个 View (MyBoxText 控件),例如,以视觉方式更新阴影颜色。

这里有一些mcve:

类(class)代码:

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()
    {

    }
}

我的渲染器的代码是这样的:

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();
    }
}

问题是,当我更改 Ghost.ShadowColor 属性时,我的“OnElementPropertyChanged”覆盖未被调用,并且 View 在屏幕上保持旧颜色。

有没有办法将 child 的“属性更新”事件传播到父 View “属性已更改”或其他方式来实现这一点?

最佳答案

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?

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

  1. 在 Shadow.cs 中 ShadowColor 的 Setter 添加 OnPropertyChanged():

    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. 像这样修改您的 MyBoxText.cs:

    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
            };
        }
    }
    

关于c# - 子属性更新调用它的父属性 `OnPropertyChanged`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48992954/

相关文章:

c# - 重写 ASP.NET 代码隐藏文件中的 Page 类构造函数——何时调用?

iphone - MonoTouch.Dialog 删除表格末尾的行

java - Xamarin:Java 绑定(bind)项目 - 无法更改本地界面的可见性

asp.net-mvc - 程序集绑定(bind)重定向不起作用

c# - Web API 中的 ContinueWith 死锁

c# - 我的项目中安装了哪个版本的 Entity Framework ?

c# - 上传多个文件时出现 TLSharp 错误

c# - 如何在Xamarin中使用MediaPlayer获得跟踪的持续时间

java - 如何通过数学运算绑定(bind)两个 SimpleDoubleProperty?

WPF Datagrid selecteditem = MVVM 中的 null