바인딩이있는 사용자 정의보기를 사용할 때 "지정된 캐스트가 유효하지 않습니다"라는 메시지가 표시되지만 수동으로 설정 한 경우에는 표시되지 않는 이유는 무엇입니까?
BindableProperty로 ObservableCollection을 사용하여 사용자 지정보기를 작성 중입니다 (내 목표는 해당 내용,이 경우 색상 목록에 따라보기의 형식을 업데이트하는 것이 었습니다). 사용자 정의보기에서 속성이 제대로 설정되었다고 생각합니다. C #에서 바인딩 가능 속성을 설정하면 작동합니다. XAML 내에서 {Binding varname}을 사용하려고하면 "Specified Cast is not Valid"오류가 발생합니다. 내 문제가 어디에 있는지 알아 내려고 노력하고 있습니다.
아래 public 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
, 사용 CollectionChanged
에 ColorBoxView
어쩌면 더 나은.
그래서 많은 검색 후에 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, null, 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 oldValue, object newValue)
{
ObservableCollection<Color> newColors = (ObservableCollection<Color>) newValue;
ColorBoxView thisView = (ColorBoxView) bindable;
thisView.Colors = newColors;
thisView.buildView(newColors);
}
}
이것이 작동하는 공식적인 이유를 알고 싶습니다. 의견을 부탁드립니다.