Xamarin表单BindableProperty在构造函数之前更改

时间:2017-10-02 10:03:08

标签: c# xaml binding xamarin.forms

我在App.xaml中通过XAML添加资源。此资源是将分配给CustomControl的隐式样式。 CustomControl包含一个标签。

要设置此标签的TextColor,我在CustomControl上创建一个可绑定属性,并使用隐式样式指定一个值。使用BindableProperty的PropertyChanged方法,我在CustomControl中设置了Label的TextColor。

<Style TargetType="CustomControl" >
     <Setter Property="InnerLabelTextColor" Value="Green" />
</Style>

-

private static void InnerLabelTextColorChanged(BindableObject bindableObject, object oldValue, object newValue)
{
    ((CustomControl)bindableObject).InnerLabel.TextColor = (Color)newValue;
}

这曾经在XF 2.3.2.127中工作但是当我更新到XF 2.3.4.270时,我开始在CustomControl中获取NullReferenceException - BindableProperty - InnerLabelTextColorChanged方法。

在执行构造函数之前调用PropertyChanged方法。执行PropertyChanged方法时,我的InnerLabel为null,导致NullReferenceException。

我想知道这种行为是否是请求的XF行为或是否是错误?

如果是请求的行为,任何人都可以提供正确的处理这种情况的方法吗?

谢谢!

编辑 - 自定义控制代码示例

public sealed class CustomControl : ContentView
{
    public static readonly BindableProperty InnerLabelTextColorProperty =
        BindableProperty.Create("InnerLabelTextColor", typeof(Color), typeof(CustomControl), Color.Black,
            BindingMode.OneWay, null, CustomControl.InnerLabelTextColorChanged, null, null, null);


    public CustomControl()
    {
        this.InnerLabel = new Label();

        this.Content = this.InnerLabel;
    }


    public Label InnerLabel { get; set; }


    public Color InnerLabelTextColor
    {
        get
        {
            return (Color)this.GetValue(CustomControl.InnerLabelTextColorProperty);
        }
        set
        {
            this.SetValue(CustomControl.InnerLabelTextColorProperty, value);
        }
    }


    private static void InnerLabelTextColorChanged(BindableObject bindableObject, object oldValue, object newValue)
    {
        ((CustomControl)bindableObject).InnerLabel.TextColor = (Color)newValue;
    }
}

1 个答案:

答案 0 :(得分:2)

我曾经在similar issue工作过一段时间,唯一的区别是它是在基于XAML的控件中遇到的。

我认为这个问题的根本原因是(当我们使用像这样的全局隐式样式时)基础构造函数尝试设置该可绑定属性,并且由于派生构造函数仍在等待轮到它,我们遇到null参考。

解决此问题的最简单方法是使用Binding设置内部子控件(reference)的属性:

public CustomControl()
{
    this.InnerLabel = new Label();

    // add inner binding
    this.InnerLabel.SetBinding(Label.TextColorProperty, 
         new Binding(nameof(InnerLabelTextColor), 
                     mode: BindingMode.OneWay, 
                     source: this));  

    this.Content = this.InnerLabel;
}