以下示例正常(https://developer.xamarin.com/samples/xamarin-forms/UserInterface/BindablePicker/)
当我尝试在我的代码中实现它时,没有设置为selectedItem引用的对象。选择器正在加载并选择数据,只是不更新对象。
以下是我正在使用的一些代码: XAML页面
<Picker x:Name="testpicker" Title="Select a Service" ItemsSource="{Binding Services}, Mode=TwoWay}" ItemDisplayBinding="{Binding ServiceDescription}" SelectedItem="{Binding SelectedServiceName, Mode=TwoWay}" />
我在视图模型中有对象,但在选择选择器项时从不调用它。:
string selectedServiceName;
public string SelectedServiceName
{
get { return selectedServiceName; }
set
{
if (selectedServiceName != value)
{
selectedServiceName = value;
PickerOnPropertyChanged();
PickerOnPropertyChanged("SelectedService");
}
}
}
当视图加载时,从控制器完成绑定....
protected async override void OnAppearing()
{
base.OnAppearing();
await viewModel.LoadPreferenceData();
await viewModel.LoadServiceData();
testpicker.SelectedIndex = 5;
}
我还更新了基类以反映教程,我更改了名称。
你能看到任何明显的原因吗?如果需要,我很乐意提供更多代码。
答案 0 :(得分:1)
错误是由于将选择器绑定到源的自定义类型。
ItemsSource="{Binding Services}
我没有使用字符串作为绑定对象,而是更改了类型:
public String SelectedServiceName
对此:
public Service SelectedServiceName
答案 1 :(得分:0)
创建自定义选择器并在您的代码中实现它为我工作尝试下面的代码:
public class CustomPicker : Picker
{
public CustomPicker()
{
SelectedIndexChanged += OnSelectedIndexChanged;
}
public static readonly BindableProperty SelectedItemProperty =
BindableProperty.Create("SelectedItem", typeof(object), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnSelectedItemChanged);
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set
{
SetValue(SelectedItemProperty, value);
if (value != null && ItemsSource!=null && ItemsSource.Contains(value))
SelectedIndex = ItemsSource.IndexOf(value);
else
SelectedIndex = -1;
}
}
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnItemsSourceChanged);
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly BindableProperty DisplayPropertyProperty =
BindableProperty.Create("DisplayProperty", typeof(string), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnDisplayPropertyChanged);
public string DisplayProperty
{
get { return (string)GetValue(DisplayPropertyProperty); }
set { SetValue(DisplayPropertyProperty, value); }
}
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
{
var picker = (CustomPicker)bindable;
picker.SelectedItem = newValue;
if (picker.ItemsSource != null && picker.SelectedItem != null)
{
var count = 0;
foreach (var obj in picker.ItemsSource)
{
if (obj == picker.SelectedItem)
{
picker.SelectedIndex = count;
break;
}
count++;
}
}
}
private static void OnDisplayPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var picker = (CustomPicker)bindable;
picker.DisplayProperty = (string)newValue;
LoadItemsAndSetSelected(bindable);
}
private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var picker = (CustomPicker)bindable;
picker.ItemsSource = (IList)newValue;
var oc = newValue as INotifyCollectionChanged;
if (oc != null)
{
oc.CollectionChanged += (a, b) =>
{
LoadItemsAndSetSelected(bindable);
};
}
LoadItemsAndSetSelected(bindable);
}
private static void LoadItemsAndSetSelected(BindableObject bindable)
{
var picker = (CustomPicker)bindable;
if (picker.ItemsSource == null)
return;
var count = 0;
foreach (var obj in picker.ItemsSource)
{
var value = string.Empty;
if (picker.DisplayProperty != null)
{
var prop = obj.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, picker.DisplayProperty, StringComparison.OrdinalIgnoreCase));
if (prop != null)
value = prop.GetValue(obj).ToString();
}
else
{
value = obj.ToString();
}
if (!picker.Items.Contains(value))
{
picker.Items.Add(value);
}
if (picker.SelectedItem != null && picker.SelectedItem == obj)
picker.SelectedIndex = count;
count++;
}
if (picker.ItemsSource.Count == picker.Items.Count - 1)
picker.SelectedIndex++;
}
private void OnSelectedIndexChanged(object sender, EventArgs e)
{
if (SelectedIndex > -1)
{
SelectedItem = ItemsSource[SelectedIndex];
}
}
}
Xaml代码
<userControls:CustomPicker BackgroundColor="Transparent" x:Name="testpicker" HorizontalOptions="FillAndExpand" ItemsSource="{Binding Services}" SelectedItem="{Binding SelectedServiceName}" DisplayProperty="{Binding ServiceDescription}" />
别忘了放入Xaml标题
xmlns:userControls="clr-namespace:MyNameSpace"