xamarin 渲染器无效转换
xamarin renderer invalid cast
为了能够创建需要在 Xamarin 环境中本地完成的样式,我使用了自定义渲染器。在 android 方面,我收到了一个 System.InvalidCastException
,我不知道如何解决这个问题。由于 this guys 对我收到的先前错误的建议(没有默认构造函数接受 0 个参数错误),我目前正在包装一个 Android.Widget.StackView
。该错误似乎不是由于声明或实例化而发生的,而是当我将其添加到 ContentView 并发生在 return 时(通过注释掉该行发现,如下所示)。
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
item1,
item2,
item3,
item4,
item5,
item6,
//rendererIWantToAdd,//taking out this line make it work. adding it breaks it
}
}
};
代码
渲染视图
public class RendererView : View
{
public static readonly BindableProperty ImageProperty = BindableProperty.Create(
propertyName: "Src",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: ""
);
public String Src
{
get { return (string)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public static readonly BindableProperty TextProperty = BindableProperty.Create(
propertyName: "Text",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "Hello World"
);
public String Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly BindableProperty ColorProperty = BindableProperty.Create(
propertyName: "Color",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "#AAAAAA"
);
public String Color
{
get { return (string) GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
}
RendererViewAndroid
[assembly: ExportRenderer(typeof(Project.RendererView), typeof(stackViewWrapper))]
namespace Project.Droid
{
public class RendererViewAndroid : ViewRenderer<RendererView, stackViewWrapper>
{
Android.Widget.TextView label;
Android.Widget.ImageView image;
protected override void OnElementChanged(ElementChangedEventArgs<RendererView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
createItem(e);
}
if (e.OldElement != null)
{
unsubscribe(e);
}
if (e.NewElement != null)
{
subscribe(e);
}
}
protected void createItem(ElementChangedEventArgs<RendererView> e)
{
SetNativeControl(new stackViewWrapper());
label = new Android.Widget.TextView(Context)
{
Text = Element.Text
};
image = new Android.Widget.ImageView(Context);
if (!string.IsNullOrWhiteSpace(Element.Src))
{
Context.Resources.GetBitmapAsync(Element.Src).ContinueWith((t) =>
{
var bitmap = t.Result;
if (bitmap != null)
{
image.SetImageBitmap(bitmap);
bitmap.Dispose();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else {
// // clear the image
image.SetImageBitmap(null);
}
Control.AddView(image);
Control.AddView(label);
}
protected void subscribe(ElementChangedEventArgs<RendererView> e)
{
}
protected void unsubscribe(ElementChangedEventArgs<RendererView> e)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public class stackViewWrapper : Android.Views.View
{
public stackViewWrapper() : base(Android.App.Application.Context)
{
}
}
}
错误堆栈跟踪
System.InvalidCastException: Specified cast is not valid.
at at (wrapper castclass) System.Object:__castclass_with_cache (object,intptr,intptr)
at Xamarin.Forms.Registrar1[TRegistrable].GetHandler (System.Type type) [0x0001b] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:24
at Xamarin.Forms.Registrar
1[TRegistrable].GetHandler[TOut] (System.Type type) [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:29
at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x00006] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:281
at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, Boolean sameChildren) [0x00023] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:72
at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00104] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:204
at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:56
at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00007] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:327
at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].SetElement (Xamarin.Forms.Platform.Android.TElement element) [0x00111] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:195
at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:128
at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:282
at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, Boolean sameChildren) [0x00023] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:72
at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00104] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:204
at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:56
at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00007] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:327
at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].SetElement (Xamarin.Forms.Platform.Android.TElement element) [0x00111] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:195
at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:128
at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:282
at Xamarin.Forms.Platform.Android.Platform.AddChild (Xamarin.Forms.VisualElement view, Boolean layout) [0x00015] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:518
at Xamarin.Forms.Platform.Android.Platform.SetPage (Xamarin.Forms.Page newRoot) [0x00089] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:406
at Xamarin.Forms.Platform.Android.FormsApplicationActivity.InternalSetPage (Xamarin.Forms.Page page) [0x000b7] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:286
at Xamarin.Forms.Platform.Android.FormsApplicationActivity.SetMainPage () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:305
at Xamarin.Forms.Platform.Android.FormsApplicationActivity.LoadApplication (Xamarin.Forms.Application application) [0x0002d] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:108
at Project.Droid.MainActivity.OnCreate (Android.OS.Bundle bundle) [0x000ae] in /Users/ryan/project-app-xamarin/Project/Project.Droid/MainActivity.cs:47
at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00011] in /Users/builder/data/lanes/3340/4e275588/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.App.Activity.cs:2426
at at (wrapper dynamic-method) System.Object:688deba4-7150-4f17-9062-10e53a94164c (intptr,intptr,intptr)
不确定这是否真的是您问题的根源,但如果不是,肯定会给您带来麻烦。
在您的 RendererView
中,您的所有绑定属性都应将其 declaringType
设置为它们在其中声明的 class,即 RendererView
。
例如,您的第一个绑定 属性 应该如下所示:
public static readonly BindableProperty ImageProperty = BindableProperty.Create(
propertyName: "Src",
returnType: typeof(string),
declaringType: typeof(RendererView),
defaultValue: ""
);
然后对所有其他人做同样的事情。如果那不能解决问题,一定要告诉我。
编辑:根据下面 OP 的评论,初始错误来自 ExportRenderer
行,需要声明 RendererView
而不是 stackViewWrapper
,如下所示:
[assembly: ExportRenderer(typeof(Project.RendererView), typeof(RendererViewAndroid))]
为了能够创建需要在 Xamarin 环境中本地完成的样式,我使用了自定义渲染器。在 android 方面,我收到了一个 System.InvalidCastException
,我不知道如何解决这个问题。由于 this guys 对我收到的先前错误的建议(没有默认构造函数接受 0 个参数错误),我目前正在包装一个 Android.Widget.StackView
。该错误似乎不是由于声明或实例化而发生的,而是当我将其添加到 ContentView 并发生在 return 时(通过注释掉该行发现,如下所示)。
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
item1,
item2,
item3,
item4,
item5,
item6,
//rendererIWantToAdd,//taking out this line make it work. adding it breaks it
}
}
};
代码
渲染视图
public class RendererView : View
{
public static readonly BindableProperty ImageProperty = BindableProperty.Create(
propertyName: "Src",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: ""
);
public String Src
{
get { return (string)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public static readonly BindableProperty TextProperty = BindableProperty.Create(
propertyName: "Text",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "Hello World"
);
public String Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly BindableProperty ColorProperty = BindableProperty.Create(
propertyName: "Color",
returnType: typeof(string),
declaringType: typeof(string),
defaultValue: "#AAAAAA"
);
public String Color
{
get { return (string) GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
}
RendererViewAndroid
[assembly: ExportRenderer(typeof(Project.RendererView), typeof(stackViewWrapper))]
namespace Project.Droid
{
public class RendererViewAndroid : ViewRenderer<RendererView, stackViewWrapper>
{
Android.Widget.TextView label;
Android.Widget.ImageView image;
protected override void OnElementChanged(ElementChangedEventArgs<RendererView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
createItem(e);
}
if (e.OldElement != null)
{
unsubscribe(e);
}
if (e.NewElement != null)
{
subscribe(e);
}
}
protected void createItem(ElementChangedEventArgs<RendererView> e)
{
SetNativeControl(new stackViewWrapper());
label = new Android.Widget.TextView(Context)
{
Text = Element.Text
};
image = new Android.Widget.ImageView(Context);
if (!string.IsNullOrWhiteSpace(Element.Src))
{
Context.Resources.GetBitmapAsync(Element.Src).ContinueWith((t) =>
{
var bitmap = t.Result;
if (bitmap != null)
{
image.SetImageBitmap(bitmap);
bitmap.Dispose();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else {
// // clear the image
image.SetImageBitmap(null);
}
Control.AddView(image);
Control.AddView(label);
}
protected void subscribe(ElementChangedEventArgs<RendererView> e)
{
}
protected void unsubscribe(ElementChangedEventArgs<RendererView> e)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
public class stackViewWrapper : Android.Views.View
{
public stackViewWrapper() : base(Android.App.Application.Context)
{
}
}
}
错误堆栈跟踪
System.InvalidCastException: Specified cast is not valid. at at (wrapper castclass) System.Object:__castclass_with_cache (object,intptr,intptr) at Xamarin.Forms.Registrar
1[TRegistrable].GetHandler (System.Type type) [0x0001b] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:24 at Xamarin.Forms.Registrar
1[TRegistrable].GetHandler[TOut] (System.Type type) [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Core\Registrar.cs:29 at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x00006] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:281 at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, Boolean sameChildren) [0x00023] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:72 at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00104] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:204 at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:56 at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00007] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:327 at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].SetElement (Xamarin.Forms.Platform.Android.TElement element) [0x00111] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:195 at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:128 at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:282 at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, Boolean sameChildren) [0x00023] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:72 at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00104] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:204 at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementPackager.cs:56 at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00007] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:327 at Xamarin.Forms.Platform.Android.VisualElementRenderer1[TElement].SetElement (Xamarin.Forms.Platform.Android.TElement element) [0x00111] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:195 at Xamarin.Forms.Platform.Android.VisualElementRenderer
1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00027] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:128 at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element) [0x0001f] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:282 at Xamarin.Forms.Platform.Android.Platform.AddChild (Xamarin.Forms.VisualElement view, Boolean layout) [0x00015] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:518 at Xamarin.Forms.Platform.Android.Platform.SetPage (Xamarin.Forms.Page newRoot) [0x00089] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\Platform.cs:406 at Xamarin.Forms.Platform.Android.FormsApplicationActivity.InternalSetPage (Xamarin.Forms.Page page) [0x000b7] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:286 at Xamarin.Forms.Platform.Android.FormsApplicationActivity.SetMainPage () [0x00000] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:305 at Xamarin.Forms.Platform.Android.FormsApplicationActivity.LoadApplication (Xamarin.Forms.Application application) [0x0002d] in C:\BuildAgent2\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\FormsApplicationActivity.cs:108 at Project.Droid.MainActivity.OnCreate (Android.OS.Bundle bundle) [0x000ae] in /Users/ryan/project-app-xamarin/Project/Project.Droid/MainActivity.cs:47 at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00011] in /Users/builder/data/lanes/3340/4e275588/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.App.Activity.cs:2426 at at (wrapper dynamic-method) System.Object:688deba4-7150-4f17-9062-10e53a94164c (intptr,intptr,intptr)
不确定这是否真的是您问题的根源,但如果不是,肯定会给您带来麻烦。
在您的 RendererView
中,您的所有绑定属性都应将其 declaringType
设置为它们在其中声明的 class,即 RendererView
。
例如,您的第一个绑定 属性 应该如下所示:
public static readonly BindableProperty ImageProperty = BindableProperty.Create(
propertyName: "Src",
returnType: typeof(string),
declaringType: typeof(RendererView),
defaultValue: ""
);
然后对所有其他人做同样的事情。如果那不能解决问题,一定要告诉我。
编辑:根据下面 OP 的评论,初始错误来自 ExportRenderer
行,需要声明 RendererView
而不是 stackViewWrapper
,如下所示:
[assembly: ExportRenderer(typeof(Project.RendererView), typeof(RendererViewAndroid))]