BindableProperty:类型不匹配
BindableProperty: Type Mismatch
我想扩展 Xamarin.Forms 选择器,以便我可以将集合绑定到它。快速搜索后,我找到了这个页面:Picker Example,其中有两个很好的例子。拒绝只是复制和粘贴代码(出于学习目的)我继续根据这两个示例制作自己的代码。
几乎完全一样,只是我的不行。
当我不向 ItemsSource 提供集合时,一切正常。每当我分配一个集合时,我都会收到以下错误:
Xamarin.Forms.Xaml.XamlParseException: Position 9:32. Cannot assign property "ItemsSource": type mismatch between "Xamarin.Forms.Binding" and "System.Collections.IEnumerable"
选择器:
public class BindablePicker : Picker
{
private static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);
private static readonly BindableProperty SelectedItemProperty =
BindableProperty.Create("SelectedItem", typeof(object), typeof(BindablePicker));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public string DisplayMember { get; set; }
private static void OnItemsSourceChanged(BindableObject bindable, Object oldValue, Object newValue)
{
var newval = newValue as IEnumerable; //Had to implement this because of the non-generic .Create() method expects Object as param.
var picker = bindable as BindablePicker;
if (picker != null)
{
picker.Items.Clear();
if (newval == null) return;
foreach (var item in newval)
{
if (string.IsNullOrEmpty(picker.DisplayMember))
{
picker.Items.Add(item.ToString());
}
else
{
var prop = item.GetType()
.GetRuntimeProperties()
.FirstOrDefault(p => string.Equals(p.Name, picker.DisplayMember, StringComparison.OrdinalIgnoreCase));
picker.Items.Add(prop.GetValue(item).ToString());
}
}
}
}
private void OnSelectedIndexChanged(object sender, EventArgs args)
{
if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
{
SelectedItem = null;
}
else
{
SelectedItem = ItemsSource.ItemOf(SelectedIndex); //ItemOf is an extension method I made for IEnumerable (has to be tested).
}
}
}
ViewModel(部分):
public class HomePageViewModel : ViewModelBase
{
//In the app this is populated with a List<Person>.
public IEnumerable<Person> People { get; set; }
}
XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:TestApp.Controls;assembly=TestApp"
x:Class="TestApp.Views.HomePage">
<ContentPage.Content>
<StackLayout>
<controls:BindablePicker ItemsSource="{Binding People}"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
请注意,链接页面中的第一个示例选择器适用于提供的 VM/View 设置。
我还没有完成选择器,我仍然想提供对 SelectedItem 的双向绑定 属性 和对 ObservableCollection 的支持。
你的,
起初我以为我要疯了。
然后我以为是什么东西严重坏了。
但我终于想通了...
private static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable),
typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);
为了让 Xaml 解析器看到 BindableProperty
本身,它必须是 public
(和 static
,但你说对了那部分) .
在你的例子中,Xaml 解析器没有看到 BindableProperty
,所以它回退到 属性,但它没有任何方法来设置 Binding
,由于类型不匹配,您会得到异常。
将您的代码更改为
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable),
typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);
我想扩展 Xamarin.Forms 选择器,以便我可以将集合绑定到它。快速搜索后,我找到了这个页面:Picker Example,其中有两个很好的例子。拒绝只是复制和粘贴代码(出于学习目的)我继续根据这两个示例制作自己的代码。
几乎完全一样,只是我的不行。
当我不向 ItemsSource 提供集合时,一切正常。每当我分配一个集合时,我都会收到以下错误:
Xamarin.Forms.Xaml.XamlParseException: Position 9:32. Cannot assign property "ItemsSource": type mismatch between "Xamarin.Forms.Binding" and "System.Collections.IEnumerable"
选择器:
public class BindablePicker : Picker
{
private static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);
private static readonly BindableProperty SelectedItemProperty =
BindableProperty.Create("SelectedItem", typeof(object), typeof(BindablePicker));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public string DisplayMember { get; set; }
private static void OnItemsSourceChanged(BindableObject bindable, Object oldValue, Object newValue)
{
var newval = newValue as IEnumerable; //Had to implement this because of the non-generic .Create() method expects Object as param.
var picker = bindable as BindablePicker;
if (picker != null)
{
picker.Items.Clear();
if (newval == null) return;
foreach (var item in newval)
{
if (string.IsNullOrEmpty(picker.DisplayMember))
{
picker.Items.Add(item.ToString());
}
else
{
var prop = item.GetType()
.GetRuntimeProperties()
.FirstOrDefault(p => string.Equals(p.Name, picker.DisplayMember, StringComparison.OrdinalIgnoreCase));
picker.Items.Add(prop.GetValue(item).ToString());
}
}
}
}
private void OnSelectedIndexChanged(object sender, EventArgs args)
{
if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
{
SelectedItem = null;
}
else
{
SelectedItem = ItemsSource.ItemOf(SelectedIndex); //ItemOf is an extension method I made for IEnumerable (has to be tested).
}
}
}
ViewModel(部分):
public class HomePageViewModel : ViewModelBase
{
//In the app this is populated with a List<Person>.
public IEnumerable<Person> People { get; set; }
}
XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:TestApp.Controls;assembly=TestApp"
x:Class="TestApp.Views.HomePage">
<ContentPage.Content>
<StackLayout>
<controls:BindablePicker ItemsSource="{Binding People}"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
请注意,链接页面中的第一个示例选择器适用于提供的 VM/View 设置。
我还没有完成选择器,我仍然想提供对 SelectedItem 的双向绑定 属性 和对 ObservableCollection 的支持。
你的,
起初我以为我要疯了。
然后我以为是什么东西严重坏了。
但我终于想通了...
private static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable),
typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);
为了让 Xaml 解析器看到 BindableProperty
本身,它必须是 public
(和 static
,但你说对了那部分) .
在你的例子中,Xaml 解析器没有看到 BindableProperty
,所以它回退到 属性,但它没有任何方法来设置 Binding
,由于类型不匹配,您会得到异常。
将您的代码更改为
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable),
typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged);