Xamarin Forms 自定义视图,Bindable Observable Collection<object> throws "Specific Cast Not Valid"
Xamarin Forms Custom View, Bindable Observable Collection<object> throws "Specific Cast Not Valid"
我在 xamarin Forms 中创建一个自定义视图,其中包含一组可绑定属性,包括我自己的模型的可绑定可观察集合类型。这些可观察的集合用作自定义视图的数据源并实时更新。一切都很好,直到添加了不同类型的模型并开始了代码重构。
自定义视图支持的模型集很少,任何时候都只能有一个类型为任何模型的可观察集合。最初我对每种类型使用不同的属性进行管理,然后为了使其更通用我尝试使用单个 属性 来处理它。那是我更换
的时候
在CustomView.cs
ObservableCollection<ModelA> ADataSource
ObservableCollection<ModelB> BDataSource
和
ObservableCollection<object> DataSource
我在 ViewModel 中有
ObservableCollection<ModelA> AList
现在,当应用程序运行时,自定义视图会为通用可观察集合抛出错误 "Specific Cast is not valid"。在 Property_Changing 事件处理程序中调试时,我能够通过快速监视将 newValue 转换为 Observable 集合。
如何处理这个问题并使通用可观察集合 属性 支持多类型模型。
提前致谢
如果你想在ContentView中使用ObservableCollection modelbs bindable 属性,那么在ContentPage中使用这个自定义控件,我做了一个例子你可以看看:
内容视图:
<ContentView
x:Class="demo3.contentview.View2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="customlistview"
mc:Ignorable="d">
<ContentView.Content>
<StackLayout>
<ListView x:Name="listview1" ItemsSource="{Binding Items, Source={x:Reference customlistview}}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding name}" />
<Label Text="{Binding age}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentView.Content>
public partial class View2 : ContentView
{
public static BindableProperty ItemsProperty = BindableProperty.Create("ItemsSource", typeof(ObservableCollection<object>), typeof(View2),null,BindingMode.TwoWay,propertyChanged: (bindable, oldValue, newValue) => OnItemsSourceChanged(bindable, oldValue, newValue));
private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var control =(View2)bindable;
control.listview1.ItemsSource =(ObservableCollection<object>) newValue;
}
/// <summary>
/// Accessors
/// </summary>
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
set
{
SetValue(ItemsProperty, value);
}
}
public View2()
{
InitializeComponent();
}
}
内容页:
<ContentPage.Content>
<StackLayout>
<local:View2 Items="{Binding modelas}" />
</StackLayout>
</ContentPage.Content>
public partial class Page26 : ContentPage
{
public ObservableCollection<object> modelas {get;set;}
public ObservableCollection<object> modelbs { get; set; }
public Page26()
{
InitializeComponent();
modelas = new ObservableCollection<object>()
{
new modela(){name="cherry",age=12},
new modela(){name="barry",age=20}
};
modelbs = new ObservableCollection<object>()
{
new modelb(){firstname="aaa",age=12},
new modelb(){firstname="bbb",age=27}
};
this.BindingContext = this;
}
}
public class modela
{
public string name { get; set; }
public int age { get; set; }
}
public class modelb
{
public string firstname { get; set; }
public int age { get; set; }
}
我在 xamarin Forms 中创建一个自定义视图,其中包含一组可绑定属性,包括我自己的模型的可绑定可观察集合类型。这些可观察的集合用作自定义视图的数据源并实时更新。一切都很好,直到添加了不同类型的模型并开始了代码重构。
自定义视图支持的模型集很少,任何时候都只能有一个类型为任何模型的可观察集合。最初我对每种类型使用不同的属性进行管理,然后为了使其更通用我尝试使用单个 属性 来处理它。那是我更换
的时候在CustomView.cs
ObservableCollection<ModelA> ADataSource
ObservableCollection<ModelB> BDataSource
和
ObservableCollection<object> DataSource
我在 ViewModel 中有
ObservableCollection<ModelA> AList
现在,当应用程序运行时,自定义视图会为通用可观察集合抛出错误 "Specific Cast is not valid"。在 Property_Changing 事件处理程序中调试时,我能够通过快速监视将 newValue 转换为 Observable 集合。
如何处理这个问题并使通用可观察集合 属性 支持多类型模型。
提前致谢
如果你想在ContentView中使用ObservableCollection modelbs bindable 属性,那么在ContentPage中使用这个自定义控件,我做了一个例子你可以看看:
内容视图:
<ContentView
x:Class="demo3.contentview.View2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="customlistview"
mc:Ignorable="d">
<ContentView.Content>
<StackLayout>
<ListView x:Name="listview1" ItemsSource="{Binding Items, Source={x:Reference customlistview}}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding name}" />
<Label Text="{Binding age}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentView.Content>
public partial class View2 : ContentView
{
public static BindableProperty ItemsProperty = BindableProperty.Create("ItemsSource", typeof(ObservableCollection<object>), typeof(View2),null,BindingMode.TwoWay,propertyChanged: (bindable, oldValue, newValue) => OnItemsSourceChanged(bindable, oldValue, newValue));
private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var control =(View2)bindable;
control.listview1.ItemsSource =(ObservableCollection<object>) newValue;
}
/// <summary>
/// Accessors
/// </summary>
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
set
{
SetValue(ItemsProperty, value);
}
}
public View2()
{
InitializeComponent();
}
}
内容页:
<ContentPage.Content>
<StackLayout>
<local:View2 Items="{Binding modelas}" />
</StackLayout>
</ContentPage.Content>
public partial class Page26 : ContentPage
{
public ObservableCollection<object> modelas {get;set;}
public ObservableCollection<object> modelbs { get; set; }
public Page26()
{
InitializeComponent();
modelas = new ObservableCollection<object>()
{
new modela(){name="cherry",age=12},
new modela(){name="barry",age=20}
};
modelbs = new ObservableCollection<object>()
{
new modelb(){firstname="aaa",age=12},
new modelb(){firstname="bbb",age=27}
};
this.BindingContext = this;
}
}
public class modela
{
public string name { get; set; }
public int age { get; set; }
}
public class modelb
{
public string firstname { get; set; }
public int age { get; set; }
}