繁体   English   中英

Xamarin在哪里执行绑定表达式?

[英]Where does Binding expression get executed in Xamarin?

我正在创建一个具有ItemsSource属性的自定义控件:

    public static readonly BindableProperty ItemsSourceProperty = 
BindableProperty.Create("ItemsSource", typeof(IEnumerable<object>), typeof(RadioButtonsGroup), defaultBindingMode: BindingMode.TwoWay);

public IEnumerable<object> ItemsSource
    {
        get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
        set
        {
            SetValue(ItemsSourceProperty, value);
            OnItemsAdded(this, new ItemsAddedEventArgs(value));
        }
    }

我在属性设置器中调用OnItemsAdded方法,以初始化控件,仅当我这样设置属性时,它才会被调用:

myCustomControl.ItemsSource = vm.MyList;

但是通过数据绑定设置它时不会被调用:

<Controls:RadioButtonsGroup ItemsSource="{Binding MyList}" x:Name="myCustomControl"/>

因此该控件不会获得列表,也不会被初始化!

我不想使用propertyChanged委托,因为它是静态的,我需要在其中使用实例成员。

这是一个示例,您应如何实现可绑定属性,即一个集合

public class RadioButtonsGroup : View
{
    public static BindableProperty ItemsSourceProperty = BindableProperty.Create(
        propertyName: nameof(ItemsSource),
        returnType: typeof(IEnumerable),
        declaringType: typeof(RadioButtonsGroup),
        defaultValue: null,
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanged: OnItemsSourceChanged
    );

    public IEnumerable ItemsSource 
    { 
        get => (IEnumerable)GetValue(ItemsSourceProperty);
        set => SetValue(ItemsSourceProperty,value);
    }

    // gets called from BindableProperty 
    // whenever you assign a new value to ItemsSource property
    private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var @this = bindable as RadioButtonsGroup;

        // unsubscribe from the old value

        var oldNPC = oldValue as INotifyPropertyChanged;
        if (oldNPC != null)
        {
            oldNPC.PropertyChanged -= @this.OnItemsSourcePropertyChanged;
        }

        var oldNCC = oldValue as INotifyCollectionChanged;
        if (oldNCC != null)
        {
            oldNCC.CollectionChanged -= @this.OnItemsSourceCollectionChanged;
        }

        // subscribe to the new value

        var newNPC = newValue as INotifyPropertyChanged;
        if (newNPC != null)
        {
            newNPC.PropertyChanged += @this.OnItemsSourcePropertyChanged;
        }

        var newNCC = newValue as INotifyCollectionChanged;
        if (newNCC != null)
        {
            newNCC.CollectionChanged += @this.OnItemsSourceCollectionChanged;
        }

        // inform the instance to do something

        @this.RebuildOnItemsSource();
    }

    private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // handle the collection changes
        throw new NotImplementedException();
    }

    private void OnItemsSourcePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // handle the property changes
        throw new NotImplementedException();
    }

    private void RebuildOnItemsSource()
    {
        if (ItemsSource == null)
        {
            // clear out all
        }
        else
        {
            // complete creation of all subviews
        }
    }
}

您需要通知绑定MyList属性已更改。 如果你有MyList在页面(的代码隐藏属性xaml.cs ),它是这样的:

public class Detail : Page, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private List<int> _myList;
    public List<int> MyList
    {
       get => _myList;
       set 
       {
          _myList = value;
          NotifyPropertyChanged();
       } 
    }    
}

如您所见,您没有在setter中订阅PropertyChanged事件,而是触发了它。 在后台, Binding订阅此事件,并且在执行该事件时,它将更新您的自定义控件上的属性的值。

要对属性更改做出反应,您需要在BindableProperty定义中添加另一个参数:

public static readonly BindableProperty ItemsSourceProperty = 
BindableProperty.Create("ItemsSource", ..., propertyChanged: OnItemsSourceChanged);

static void OnEventNameChanged (BindableObject bindable, object oldValue, object newValue)
{
    // Property changed implementation goes here
}

有一个很好的教程,用于构建具有可绑定属性的自定义控件: https : //mindofai.github.io/Creating-Custom-Controls-with-Bindable-Properties-in-Xamarin.Forms/

暂无
暂无

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

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