如何解决为什么在使用具有绑定的自定义视图时却出现“指定的演员表无效”,但在手动设置时却没有,为什么?
我正在使用ObservableCollection作为BindableProperty构建自定义视图(我的目标是根据视图的内容(在本例中为颜色列表)更新视图的格式。我认为我已经在自定义视图中正确设置了属性。如果我在C#中设置了bindable属性,它将起作用。如果我尝试在XAML中使用{Binding varname},则会引发“指定的演员转换无效”错误。我正在尝试找出问题所在。
在公共MainPage()的下面,您可以看到注释行,在该行中我手动设置了属性。如果我取消注释并从MainPage.xaml中删除“ Color = {Binding Test}”,则一切正常。如果按原样运行,则会出现异常。
这是我所有的代码:
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public ObservableCollection<Color> Test { get; set; }
public MainPage()
{
Test = new ObservableCollection<Color>();
Test.Add(Color.Blue);
Test.Add(Color.Green);
Test.Add(Color.Red);
Test.Add(Color.Purple);
this.BindingContext = this;
InitializeComponent();
//myView.Colors = Test;
}
private void OnClicked(object sender,EventArgs e)
{
myView.Colors.Add(Color.Yellow);
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ColorBoxes"
x:Class="ColorBoxes.MainPage">
<StackLayout HorizontalOptions="CenterAndExpand">
<local:ColorBoxView x:Name="myView" Colors="{Binding Test}" WidthRequest="400" HeightRequest="600"/>
<Button Text="Add Color" Clicked="OnClicked"/>
</StackLayout>
</ContentPage>
ColorBoxView.xaml.cs
public partial class ColorBoxView : ContentView
{
public ColorBoxView()
{
InitializeComponent();
}
public static BindableProperty ColorList = BindableProperty.Create(
propertyName: "Colors",returnType: typeof(ObservableCollection<Color>),declaringType: typeof(ColorBoxView),defaultValue: new ObservableCollection<Color>(),defaultBindingMode: BindingMode.OneWay,propertyChanged: HandleColorListPropertyChanged
);
public ObservableCollection<Color> Colors
{
get { return (ObservableCollection<Color>) base.GetValue(ColorList); }
set
{
if (value != this.Colors)
{
base.SetValue(ColorList,value);
Colors.CollectionChanged += Items_CollectionChanged;
}
}
}
void Items_CollectionChanged(object sender,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
buildView(Colors);
}
private void buildView(ObservableCollection<Color> newColors)
{
/* This code is never reached */
}
private static void HandleColorListPropertyChanged(BindableObject bindable,object oldValue,object newValue)
{
ObservableCollection<Color> newColors = (ObservableCollection<Color>) newValue;
ColorBoxView thisView = (ColorBoxView) bindable;
thisView.buildView(newColors);
}
ColorBoxView.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ColorBoxes.ColorBoxView" >
<Grid x:Name="BoxGrid" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
RowSpacing="0" ColumnSpacing="0" Padding="0">
</Grid>
</ContentView>
堆栈跟踪:
System.InvalidCastException: Specified cast is not valid.
at ColorBoxes.MainPage.InitializeComponent () [0x00023] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/obj/Debug/netstandard2.0/MainPage.xaml.g.cs:26
at ColorBoxes.MainPage..ctor () [0x00060] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/MainPage.xaml.cs:25
at ColorBoxes.App..ctor () [0x0000f] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes/App.xaml.cs:15
at ColorBoxes.iOS.AppDelegate.FinishedLaunching (UIKit.UIApplication app,Foundation.NSDictionary options) [0x00007] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes.iOS/AppDelegate.cs:25
at at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args,System.IntPtr principal,System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIApplication.cs:86
at UIKit.UIApplication.Main (System.String[] args,System.String principalClassName,System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIApplication.cs:65
at ColorBoxes.iOS.Application.Main (System.String[] args) [0x00001] in /Users/docmani/RiderProjects/ColorBoxes/ColorBoxes/ColorBoxes.iOS/Main.cs:16
其他信息-一段时间以来,我尝试在NuGet中升级Xamarin.Forms。现在它甚至不会与绑定一起编译。它给了我
MainPage.xaml(9,46): [XFC0009] No property,BindableProperty,or event found for "Colors",or mismatching type between value and property.
但是,再次提醒一下,如果我在C#中手动设置该值,它将仍然有效。我肯定在XAML中缺少某些内容,但我不知道它是什么。
解决方法
您可以像BindableProperty
一样更改ColorListProperty
,然后在xaml中进行测试。
public partial class ColorBoxView : ContentView
{
public ColorBoxView ()
{
InitializeComponent ();
}
public static readonly BindableProperty ColorListProperty = BindableProperty.Create(
nameof(ColorList),typeof(ObservableCollection<object>),typeof(ColorBoxView),new ObservableCollection<object>(),BindingMode.OneWay,propertyChanged: ContractListPropertyChangedDelegate);
public ObservableCollection<object> ColorList
{
get =>
(ObservableCollection<object>)GetValue(ColorListProperty);
set => SetValue(ColorListProperty,value);
}
private static void ContractListPropertyChangedDelegate(BindableObject bindable,object oldValue,object newValue)
{
// throw new NotImplementedException();
// ColorBoxView colorBoxView= bindable as ColorBoxView;
}
<local:ColorBoxView x:Name="myView" ColorList="{Binding Test}" WidthRequest="400" HeightRequest="600"/>
如果要执行CollectionChanged
事件,请在单击按钮时将 ColorList.CollectionChanged += ColorList_CollectionChanged
添加到ColorBoxView
的构造函数中。
public ColorBoxView ()
{
InitializeComponent ();
ColorList.CollectionChanged += ColorList_CollectionChanged;
}
private void ColorList_CollectionChanged(object sender,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// throw new NotImplementedException();
}
当您设置新的set
时,将执行您的ObservableCollection
方法,如果只是将项目添加到已存在的ObservableCollection
,请在{{1 }}可能更好。
因此,经过多次搜索,我发现了几个示例,其中BindingProperty的类型设置为“ IEnumerable”。重做代码后,我想到了以下可行的方法:
public partial class ColorBoxView : ContentView
{
public ColorBoxView()
{
InitializeComponent();
}
public static readonly BindableProperty ColorsProperty =
BindableProperty.Create (nameof (Colors),typeof (IEnumerable),typeof (ColorBoxView),null,BindingMode.Default,HandleColorListPropertyChanged);
public IEnumerable Colors
{
get { return (IEnumerable) GetValue (ColorsProperty); }
set
{
SetValue (ColorsProperty,value);
var oc = (ObservableCollection<Color>) (this.Colors);
oc.CollectionChanged += Items_CollectionChanged;
}
}
private void Items_CollectionChanged(object sender,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
buildView( (ObservableCollection<Color>)Colors);
}
private void buildView(ObservableCollection<Color> newColors)
{
/* Update code */
}
private static void HandleColorListPropertyChanged(BindableObject bindable,object newValue)
{
ObservableCollection<Color> newColors = (ObservableCollection<Color>) newValue;
ColorBoxView thisView = (ColorBoxView) bindable;
thisView.Colors = newColors;
thisView.buildView(newColors);
}
}
我很想知道这样做的正式原因。感谢评论。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。