我正在创建一个具有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
委托,因为它是静态的,我需要在其中使用实例成员。
答案 0 :(得分:2)
这是一个如何实现可绑定属性的示例,即集合
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
}
}
}
答案 1 :(得分:0)
您需要通知绑定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/