[C] Use a Binding for ItemsSource object selection

This commit is contained in:
Stephane Delcroix 2016-11-09 15:15:12 +01:00 коммит произвёл Jason Smith
Родитель 693cc75068
Коммит e5af21fdc3
7 изменённых файлов: 400 добавлений и 307 удалений

Просмотреть файл

@ -5,57 +5,57 @@ using System.Globalization;
namespace Xamarin.Forms.Core.UnitTests
{
internal class ContextFixture
{
public class NestedClass
{
public string Nested { get; set; }
}
public NestedClass Nested { get; set; }
public string DisplayName { get; set; }
public string ComplexName { get; set; }
public ContextFixture(string displayName, string complexName)
{
DisplayName = displayName;
ComplexName = complexName;
}
public ContextFixture()
{
}
}
internal class BindingContext
{
public ObservableCollection<object> Items { get; set; }
public object SelectedItem { get; set; }
}
internal class PickerTestValueConverter : IValueConverter
{
public bool ConvertCalled { get; private set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ConvertCalled = true;
var cf = (ContextFixture)value;
return cf.DisplayName;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[TestFixture]
public class PickerTests : BaseTestFixture
{
class PickerTestsContextFixture
{
public class PickerTestsNestedClass
{
public string Nested { get; set; }
}
public PickerTestsNestedClass Nested { get; set; }
public string DisplayName { get; set; }
public string ComplexName { get; set; }
public PickerTestsContextFixture(string displayName, string complexName)
{
DisplayName = displayName;
ComplexName = complexName;
}
public PickerTestsContextFixture()
{
}
}
class PickerTestsBindingContext
{
public ObservableCollection<object> Items { get; set; }
public object SelectedItem { get; set; }
}
class PickerTestValueConverter : IValueConverter
{
public bool ConvertCalled { get; private set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ConvertCalled = true;
var cf = (PickerTestsContextFixture)value;
return cf.DisplayName;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[Test]
public void TestSetSelectedIndexOnNullRows()
{
@ -185,28 +185,6 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual(0, picker.Items.Count);
}
[Test]
public void TestDisplayFunc()
{
Func<object, string> customDisplayFunc = o =>
{
var f = (ContextFixture)o;
return $"{f.DisplayName} ({f.ComplexName})";
};
var obj = new ContextFixture("Monkey", "Complex Monkey");
var picker = new Picker
{
DisplayMemberPath = "Name",
DisplayFunc = customDisplayFunc,
ItemsSource = new ObservableCollection<object>
{
obj
},
SelectedIndex = 1
};
Assert.AreEqual("Monkey (Complex Monkey)", picker.Items[0]);
}
[Test]
public void TestSetItemsSourceProperty()
{
@ -220,22 +198,22 @@ namespace Xamarin.Forms.Core.UnitTests
};
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
ItemsSource = items
};
Assert.AreEqual(5, picker.Items.Count);
Assert.AreEqual("John", picker.Items[0]);
Assert.AreEqual("0", picker.Items[3]);
Assert.AreEqual(null, picker.Items[3]);
}
[Test]
public void TestDisplayConverter()
{
var obj = new ContextFixture("John", "John Doe");
var obj = new PickerTestsContextFixture("John", "John Doe");
var converter = new PickerTestValueConverter();
var picker = new Picker
{
DisplayConverter = converter,
ItemDisplayBinding = new Binding (Binding.SelfPath, converter:converter),
ItemsSource = new ObservableCollection<object>
{
obj
@ -245,22 +223,6 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual("John", picker.Items[0]);
}
[Test]
public void TestDisplayMemberPathShouldThrowArgumentExceptionInvalidPath()
{
var obj = new ContextFixture("Monkey", "Complex Monkey");
Func<Picker> picker = () => new Picker
{
DisplayMemberPath = "Name",
ItemsSource = new ObservableCollection<object>
{
obj
},
SelectedIndex = 1
};
Assert.Throws<ArgumentException>(() => picker());
}
[Test]
public void TestItemsSourceCollectionChangedAppend()
{
@ -272,7 +234,7 @@ namespace Xamarin.Forms.Core.UnitTests
};
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
ItemsSource = items,
SelectedIndex = 0
};
@ -294,7 +256,7 @@ namespace Xamarin.Forms.Core.UnitTests
};
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
ItemsSource = items,
SelectedIndex = 0
};
@ -314,7 +276,7 @@ namespace Xamarin.Forms.Core.UnitTests
};
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
ItemsSource = items,
SelectedIndex = 0
};
@ -337,7 +299,7 @@ namespace Xamarin.Forms.Core.UnitTests
var bindingContext = new { Items = items };
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
BindingContext = bindingContext
};
picker.SetBinding(Picker.ItemsSourceProperty, "Items");
@ -348,6 +310,7 @@ namespace Xamarin.Forms.Core.UnitTests
"Orange"
};
picker.BindingContext = new { Items = items };
picker.ItemDisplayBinding = null;
Assert.AreEqual(2, picker.Items.Count);
Assert.AreEqual("Peach", picker.Items[0]);
}
@ -358,12 +321,12 @@ namespace Xamarin.Forms.Core.UnitTests
var items = new ObservableCollection<object>
{
new { Name = "John" },
"Paul",
"Ringo"
new { Name = "Paul" },
new { Name = "Ringo"},
};
var picker = new Picker
{
DisplayMemberPath = "Name",
ItemDisplayBinding = new Binding("Name"),
ItemsSource = items,
SelectedIndex = 0
};
@ -395,11 +358,11 @@ namespace Xamarin.Forms.Core.UnitTests
[Test]
public void TestSelectedItemDefault()
{
var bindingContext = new BindingContext
var bindingContext = new PickerTestsBindingContext
{
Items = new ObservableCollection<object>
{
new ContextFixture("John", "John")
new PickerTestsContextFixture("John", "John")
}
};
var picker = new Picker
@ -413,19 +376,28 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual(bindingContext.SelectedItem, picker.SelectedItem);
}
[Test]
public void ThrowsWhenModifyingItemsIfItemsSourceIsSet()
{
var picker = new Picker {
ItemsSource = new System.Collections.Generic.List<object> ()
};
Assert.Throws<InvalidOperationException>(() => picker.Items.Add("foo"));
}
[Test]
public void TestNestedDisplayMemberPathExpression()
{
var obj = new ContextFixture
var obj = new PickerTestsContextFixture
{
Nested = new ContextFixture.NestedClass
Nested = new PickerTestsContextFixture.PickerTestsNestedClass
{
Nested = "NestedProperty"
}
};
var picker = new Picker
{
DisplayMemberPath = "Nested.Nested",
ItemDisplayBinding = new Binding("Nested.Nested"),
ItemsSource = new ObservableCollection<object>
{
obj
@ -454,8 +426,8 @@ namespace Xamarin.Forms.Core.UnitTests
[Test]
public void TestSelectedItemSet()
{
var obj = new ContextFixture("John", "John");
var bindingContext = new BindingContext
var obj = new PickerTestsContextFixture("John", "John");
var bindingContext = new PickerTestsBindingContext
{
Items = new ObservableCollection<object>
{
@ -466,7 +438,7 @@ namespace Xamarin.Forms.Core.UnitTests
var picker = new Picker
{
BindingContext = bindingContext,
DisplayMemberPath = "DisplayName"
ItemDisplayBinding = new Binding("DisplayName"),
};
picker.SetBinding(Picker.ItemsSourceProperty, "Items");
picker.SetBinding(Picker.SelectedItemProperty, "SelectedItem");
@ -478,8 +450,8 @@ namespace Xamarin.Forms.Core.UnitTests
[Test]
public void TestSelectedItemChangeSelectedIndex()
{
var obj = new ContextFixture("John", "John");
var bindingContext = new BindingContext
var obj = new PickerTestsContextFixture("John", "John");
var bindingContext = new PickerTestsBindingContext
{
Items = new ObservableCollection<object>
{
@ -489,7 +461,7 @@ namespace Xamarin.Forms.Core.UnitTests
var picker = new Picker
{
BindingContext = bindingContext,
DisplayMemberPath = "DisplayName"
ItemDisplayBinding = new Binding("DisplayName"),
};
picker.SetBinding(Picker.ItemsSourceProperty, "Items");
picker.SetBinding(Picker.SelectedItemProperty, "SelectedItem");

Просмотреть файл

@ -2,8 +2,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Reflection;
using Xamarin.Forms.Platform;
namespace Xamarin.Forms
@ -11,63 +9,33 @@ namespace Xamarin.Forms
[RenderWith(typeof(_PickerRenderer))]
public class Picker : View, IElementConfiguration<Picker>
{
public static readonly BindableProperty TextColorProperty = BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(Picker), Color.Default);
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(Picker), Color.Default);
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(Picker), default(string));
public static readonly BindableProperty TitleProperty =
BindableProperty.Create(nameof(Title), typeof(string), typeof(Picker), default(string));
public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(Picker), -1, BindingMode.TwoWay,
propertyChanged: OnSelectedIndexChanged,
coerceValue: CoerceSelectedIndex);
public static readonly BindableProperty SelectedIndexProperty =
BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(Picker), -1, BindingMode.TwoWay,
propertyChanged: OnSelectedIndexChanged, coerceValue: CoerceSelectedIndex);
public static readonly BindableProperty SelectedValueMemberPathProperty = BindableProperty.Create(nameof(SelectedValueMemberPath), typeof(string), typeof(Picker));
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(Picker), default(IList),
propertyChanged: OnItemsSourceChanged);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(Picker), default(IList), propertyChanged: OnItemsSourceChanged);
public static readonly BindableProperty DisplayMemberPathProperty = BindableProperty.Create(nameof(DisplayMemberPath), typeof(string), typeof(Picker), propertyChanged: OnDisplayMemberPathChanged);
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(Picker), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
public static readonly BindableProperty SelectedItemProperty =
BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(Picker), null, BindingMode.TwoWay,
propertyChanged: OnSelectedItemChanged);
readonly Lazy<PlatformConfigurationRegistry<Picker>> _platformConfigurationRegistry;
public static readonly BindableProperty DisplayFuncProperty =
BindableProperty.Create(
nameof(DisplayFunc),
typeof(Func<object, string>),
typeof(Picker));
public static readonly BindableProperty DisplayConverterProperty =
BindableProperty.Create(
nameof(DisplayConverter),
typeof(IValueConverter),
typeof(Picker),
default(IValueConverter));
public Picker()
{
((ObservableList<string>)Items).CollectionChanged += OnItemsCollectionChanged;
((INotifyCollectionChanged)Items).CollectionChanged += OnItemsCollectionChanged;
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Picker>>(() => new PlatformConfigurationRegistry<Picker>(this));
}
public string DisplayMemberPath
{
get { return (string)GetValue(DisplayMemberPathProperty); }
set { SetValue(DisplayMemberPathProperty, value); }
}
public Func<object, string> DisplayFunc
{
get { return (Func<object, string>)GetValue(DisplayFuncProperty); }
set { SetValue(DisplayFuncProperty, value); }
}
public IValueConverter DisplayConverter
{
get { return (IValueConverter)GetValue(DisplayConverterProperty); }
set { SetValue(DisplayConverterProperty, value); }
}
public IList<string> Items { get; } = new ObservableList<string>();
public IList<string> Items { get; } = new LockableObservableListWrapper();
public IList ItemsSource
{
@ -87,73 +55,44 @@ namespace Xamarin.Forms
set { SetValue(SelectedItemProperty, value); }
}
public string SelectedValueMemberPath
{
get { return (string)GetValue(SelectedValueMemberPathProperty); }
set { SetValue(SelectedValueMemberPathProperty, value); }
}
public Color TextColor
{
public Color TextColor {
get { return (Color)GetValue(TextColorProperty); }
set { SetValue(TextColorProperty, value); }
}
public string Title
{
public string Title {
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
BindingBase _itemDisplayBinding;
public BindingBase ItemDisplayBinding {
get { return _itemDisplayBinding; }
set {
if (_itemDisplayBinding == value)
return;
OnPropertyChanging();
var oldValue = value;
_itemDisplayBinding = value;
OnItemDisplayBindingChanged(oldValue, _itemDisplayBinding);
OnPropertyChanged();
}
}
public event EventHandler SelectedIndexChanged;
protected virtual string GetDisplayMember(object item)
static readonly BindableProperty s_displayProperty =
BindableProperty.Create("Display", typeof(string), typeof(Picker), default(string));
string GetDisplayMember(object item)
{
if (DisplayConverter != null)
{
var display = DisplayConverter.Convert(item, typeof(string), null, CultureInfo.CurrentUICulture) as string;
if (display == null)
{
throw new ArgumentException("value must be converted to string");
}
return display;
}
if (DisplayFunc != null)
{
return DisplayFunc(item);
}
if (item == null)
{
return null;
}
bool isValueType = item.GetType().GetTypeInfo().IsValueType;
if (isValueType || string.IsNullOrEmpty(DisplayMemberPath) || item is string)
{
// For a mix of objects in ItemsSourc to be handled correctly in conjunction with DisplayMemberPath
// we need to handle value types and string so that GetPropertyValue doesn't throw exception if the property
// doesn't exist on the item object
if (ItemDisplayBinding == null)
return item.ToString();
}
return GetPropertyValue(item, DisplayMemberPath) as string;
}
void AddItems(NotifyCollectionChangedEventArgs e)
{
int index = e.NewStartingIndex < 0 ? Items.Count : e.NewStartingIndex;
foreach (object newItem in e.NewItems)
{
Items.Insert(index++, GetDisplayMember(newItem));
}
}
void BindItems()
{
Items.Clear();
foreach (object item in ItemsSource)
{
Items.Add(GetDisplayMember(item));
}
UpdateSelectedItem();
ItemDisplayBinding.Apply(item, this, s_displayProperty);
ItemDisplayBinding.Unapply();
return (string)GetValue(s_displayProperty);
}
static object CoerceSelectedIndex(BindableObject bindable, object value)
@ -162,60 +101,9 @@ namespace Xamarin.Forms
return picker.Items == null ? -1 : ((int)value).Clamp(-1, picker.Items.Count - 1);
}
void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
void OnItemDisplayBindingChanged(BindingBase oldValue, BindingBase newValue)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
// Clear Items collection and re-populate it with values from ItemsSource
BindItems();
return;
case NotifyCollectionChangedAction.Remove:
RemoveItems(e);
break;
case NotifyCollectionChangedAction.Add:
AddItems(e);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
static object GetPropertyValue(object item, string memberPath)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
if (string.IsNullOrEmpty(memberPath))
{
throw new ArgumentNullException(nameof(memberPath));
}
// Find the property by walking the display member path to find any nested properties
string[] propertyPathParts = memberPath.Split('.');
object propertyValue = item;
foreach (string propertyPathPart in propertyPathParts)
{
PropertyInfo propInfo = propertyValue.GetType().GetTypeInfo().GetDeclaredProperty(propertyPathPart);
if (propInfo == null)
{
throw new ArgumentException(
$"No property with name '{propertyPathPart}' was found on '{propertyValue.GetType().FullName}'");
}
propertyValue = propInfo.GetValue(propertyValue);
}
return propertyValue;
}
static void OnDisplayMemberPathChanged(BindableObject bindable, object oldValue, object newValue)
{
var picker = (Picker)bindable;
if (picker.ItemsSource?.Count > 0)
{
picker.BindItems();
}
ResetItems();
}
void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
@ -226,31 +114,71 @@ namespace Xamarin.Forms
static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var picker = (Picker)bindable;
// Check if the ItemsSource value has changed and if so, unsubscribe from collection changed
var observable = oldValue as INotifyCollectionChanged;
if (observable != null)
{
observable.CollectionChanged -= picker.CollectionChanged;
((Picker)bindable).OnItemsSourceChanged((IList)oldValue, (IList)newValue);
}
void OnItemsSourceChanged(IList oldValue, IList newValue)
{
var oldObservable = oldValue as INotifyCollectionChanged;
if (oldObservable != null)
oldObservable.CollectionChanged -= CollectionChanged;
var newObservable = newValue as INotifyCollectionChanged;
if (newObservable != null) {
newObservable.CollectionChanged += CollectionChanged;
}
observable = newValue as INotifyCollectionChanged;
if (observable != null)
{
observable.CollectionChanged += picker.CollectionChanged;
picker.BindItems();
if (newValue != null) {
((LockableObservableListWrapper)Items).IsLocked = true;
ResetItems();
} else {
((LockableObservableListWrapper)Items).InternalClear();
((LockableObservableListWrapper)Items).IsLocked = false;
}
else
{
// newValue is null so clear the items collection
picker.Items.Clear();
}
void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action) {
case NotifyCollectionChangedAction.Add:
AddItems(e);
break;
case NotifyCollectionChangedAction.Remove:
RemoveItems(e);
break;
default: //Move, Replace, Reset
ResetItems();
break;
}
}
void AddItems(NotifyCollectionChangedEventArgs e)
{
int index = e.NewStartingIndex < 0 ? Items.Count : e.NewStartingIndex;
foreach (object newItem in e.NewItems)
((LockableObservableListWrapper)Items).InternalInsert(index++, GetDisplayMember(newItem));
}
void RemoveItems(NotifyCollectionChangedEventArgs e)
{
int index = e.OldStartingIndex < Items.Count ? e.OldStartingIndex : Items.Count;
foreach (object _ in e.OldItems)
((LockableObservableListWrapper)Items).InternalRemoveAt(index--);
}
void ResetItems()
{
if (ItemsSource == null)
return;
((LockableObservableListWrapper)Items).InternalClear();
foreach (object item in ItemsSource)
((LockableObservableListWrapper)Items).InternalAdd(GetDisplayMember(item));
UpdateSelectedItem();
}
static void OnSelectedIndexChanged(object bindable, object oldValue, object newValue)
{
var picker = (Picker)bindable;
EventHandler eh = picker.SelectedIndexChanged;
eh?.Invoke(bindable, EventArgs.Empty);
picker.SelectedIndexChanged?.Invoke(bindable, EventArgs.Empty);
picker.UpdateSelectedItem();
}
@ -260,34 +188,146 @@ namespace Xamarin.Forms
picker.UpdateSelectedIndex(newValue);
}
void RemoveItems(NotifyCollectionChangedEventArgs e)
{
int index = e.OldStartingIndex < Items.Count ? e.OldStartingIndex : Items.Count;
// TODO: How do we determine the order of which the items were removed
foreach (object _ in e.OldItems)
{
Items.RemoveAt(index--);
}
}
void UpdateSelectedIndex(object selectedItem)
{
string displayMember = GetDisplayMember(selectedItem);
int index = Items.IndexOf(displayMember);
// TODO Should we prevent call to FindObject since the object is already known
// by setting a flag, or otherwise indicate, that we, internally, forced a SelectedIndex changed
SelectedIndex = index;
if (ItemsSource != null) {
SelectedIndex = ItemsSource.IndexOf(selectedItem);
return;
}
SelectedIndex = Items.IndexOf(selectedItem);
}
void UpdateSelectedItem()
{
// coerceSelectedIndex ensures that SelectedIndex is in range [-1,ItemsSource.Count)
SelectedItem = SelectedIndex == -1 ? null : ItemsSource?[SelectedIndex];
if (SelectedIndex == -1) {
SelectedItem = null;
return;
}
if (ItemsSource != null) {
SelectedItem = ItemsSource [SelectedIndex];
return;
}
SelectedItem = Items [SelectedIndex];
}
public IPlatformElementConfiguration<T, Picker> On<T>() where T : IConfigPlatform
{
return _platformConfigurationRegistry.Value.On<T>();
}
class LockableObservableListWrapper : INotifyCollectionChanged, IList<string>
{
readonly ObservableList<string> _list = new ObservableList<string>();
public bool IsLocked { get; set; }
event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged {
add { _list.CollectionChanged += value; }
remove { _list.CollectionChanged -= value; }
}
void ThrowOnLocked()
{
if (IsLocked)
throw new InvalidOperationException("The Items list can not be manipulated if the ItemsSource property is set");
}
public string this [int index] {
get { return _list [index]; }
set {
ThrowOnLocked();
_list [index] = value; }
}
public int Count {
get { return _list.Count; }
}
public bool IsReadOnly {
get { return ((IList<string>)_list).IsReadOnly; }
}
public void InternalAdd(string item)
{
_list.Add(item);
}
public void Add(string item)
{
ThrowOnLocked();
InternalAdd(item);
}
public void InternalClear()
{
_list.Clear();
}
public void Clear()
{
ThrowOnLocked();
InternalClear();
}
public bool Contains(string item)
{
return _list.Contains(item);
}
public void CopyTo(string [] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public IEnumerator<string> GetEnumerator()
{
return _list.GetEnumerator();
}
public int IndexOf(string item)
{
return _list.IndexOf(item);
}
public void InternalInsert(int index, string item)
{
_list.Insert(index, item);
}
public void Insert(int index, string item)
{
ThrowOnLocked();
InternalInsert(index, item);
}
public bool InternalRemove(string item)
{
return _list.Remove(item);
}
public bool Remove(string item)
{
ThrowOnLocked();
return InternalRemove(item);
}
public void InternalRemoveAt(int index)
{
_list.RemoveAt(index);
}
public void RemoveAt(int index)
{
ThrowOnLocked();
InternalRemoveAt(index);
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_list).GetEnumerator();
}
}
}
}
}

Просмотреть файл

@ -6,6 +6,7 @@ using Android.Content.Res;
using Android.Text;
using Android.Widget;
using Object = Java.Lang.Object;
using System.Collections.Specialized;
namespace Xamarin.Forms.Platform.Android.AppCompat
{
@ -31,7 +32,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
{
_disposed = true;
((ObservableList<string>)Element.Items).CollectionChanged -= RowsCollectionChanged;
((INotifyCollectionChanged)Element.Items).CollectionChanged -= RowsCollectionChanged;
}
base.Dispose(disposing);
@ -40,11 +41,11 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
if (e.OldElement != null)
((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
((INotifyCollectionChanged)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
if (e.NewElement != null)
{
((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
((INotifyCollectionChanged)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
if (Control == null)
{
EditText textField = CreateNativeControl();

Просмотреть файл

@ -9,6 +9,7 @@ using ADatePicker = Android.Widget.DatePicker;
using ATimePicker = Android.Widget.TimePicker;
using Object = Java.Lang.Object;
using Orientation = Android.Widget.Orientation;
using System.Collections.Specialized;
namespace Xamarin.Forms.Platform.Android
{
@ -30,7 +31,7 @@ namespace Xamarin.Forms.Platform.Android
if (disposing && !_isDisposed)
{
_isDisposed = true;
((ObservableList<string>)Element.Items).CollectionChanged -= RowsCollectionChanged;
((INotifyCollectionChanged)Element.Items).CollectionChanged -= RowsCollectionChanged;
}
base.Dispose(disposing);
@ -44,11 +45,11 @@ namespace Xamarin.Forms.Platform.Android
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
if (e.OldElement != null)
((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
((INotifyCollectionChanged)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
if (e.NewElement != null)
{
((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
((INotifyCollectionChanged)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
if (Control == null)
{
var textField = CreateNativeControl();

Просмотреть файл

@ -27,9 +27,9 @@ namespace Xamarin.Forms.Platform.WinPhone
base.OnElementChanged(e);
if (e.OldElement != null)
((ObservableList<string>)Element.Items).CollectionChanged -= ItemsCollectionChanged;
((INotifyCollectionChanged)Element.Items).CollectionChanged -= ItemsCollectionChanged;
((ObservableList<string>)Element.Items).CollectionChanged += ItemsCollectionChanged;
((INotifyCollectionChanged)Element.Items).CollectionChanged += ItemsCollectionChanged;
_listPicker.ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerItemTemplate"];
_listPicker.FullModeItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerFullItemTemplate"];

Просмотреть файл

@ -1,4 +1,5 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using UIKit;
using RectangleF = CoreGraphics.CGRect;
@ -15,7 +16,7 @@ namespace Xamarin.Forms.Platform.iOS
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
if (e.OldElement != null)
((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
((INotifyCollectionChanged)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
if (e.NewElement != null)
{
@ -55,7 +56,7 @@ namespace Xamarin.Forms.Platform.iOS
UpdatePicker();
UpdateTextColor();
((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
((INotifyCollectionChanged)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
}
base.OnElementChanged(e);

Просмотреть файл

@ -163,6 +163,22 @@ namespace FormsGallery
</remarks>
</Docs>
</Member>
<Member MemberName="ItemDisplayBinding">
<MemberSignature Language="C#" Value="public Xamarin.Forms.BindingBase ItemDisplayBinding { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindingBase ItemDisplayBinding" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.BindingBase</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Items">
<MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;string&gt; Items { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;string&gt; Items" />
@ -185,6 +201,37 @@ namespace FormsGallery
<remarks>This property is read-only, but exposes the IList&lt;&gt; interface, so items can be added using Add().</remarks>
</Docs>
</Member>
<Member MemberName="ItemsSource">
<MemberSignature Language="C#" Value="public System.Collections.IList ItemsSource { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.IList ItemsSource" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Collections.IList</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="ItemsSourceProperty">
<MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemsSourceProperty;" />
<MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemsSourceProperty" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="On&lt;T&gt;">
<MemberSignature Language="C#" Value="public Xamarin.Forms.IPlatformElementConfiguration&lt;T,Xamarin.Forms.Picker&gt; On&lt;T&gt; () where T : Xamarin.Forms.IConfigPlatform;" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class Xamarin.Forms.IPlatformElementConfiguration`2&lt;!!T, class Xamarin.Forms.Picker&gt; On&lt;(class Xamarin.Forms.IConfigPlatform) T&gt;() cil managed" />
@ -275,6 +322,37 @@ namespace FormsGallery
</remarks>
</Docs>
</Member>
<Member MemberName="SelectedItem">
<MemberSignature Language="C#" Value="public object SelectedItem { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance object SelectedItem" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Object</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="SelectedItemProperty">
<MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SelectedItemProperty;" />
<MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SelectedItemProperty" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="TextColor">
<MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />