Search code examples
xamlxamarinxamarin.formsxamarin.androidxamarin.ios

Xamarin Forms Common Reusable Views


I'm trying to make a reusable view for password toggle visibility to use it in many places. however i can't find a proper way to do it. here is my view code

    <Grid>
        <Entry 
        Placeholder="{xct:Translate Password}"
        IsPassword="{Binding Source={x:Reference ShowPasswordActualTrigger}, Path=HidePassword}"
        Text="{Binding Password}"
        Style="{StaticResource EntryStyle}"
        />
        <ImageButton 
                VerticalOptions="Center"
                Margin="0,0,10,10"
                HeightRequest="40"
                WidthRequest="30"
                HorizontalOptions="End"
                BackgroundColor="Transparent"
                Source="{local:ImageResource RealEstateDemo.Images.eye-hidden.png}">
            <ImageButton.Triggers>
                <EventTrigger Event="Clicked">
                    <trigger:ShowPasswordTriggerAction 
                    ShowIcon="{local:ImageResource RealEstateDemo.Images.eye-show.png}"
                    HideIcon="{local:ImageResource RealEstateDemo.Images.eye-hidden.png}"
                    x:Name="ShowPasswordActualTrigger"/>
                </EventTrigger>
            </ImageButton.Triggers>
        </ImageButton>
<Grid/>

and my reusable view code am trying to separate the image button code

<ImageButton   
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="RealEstateDemo.Common.Views.PasswordToggle"
        VerticalOptions="Center"
        Margin="0,0,10,10"
        HeightRequest="40"
        WidthRequest="30"
        HorizontalOptions="End"
        BackgroundColor="Transparent"
        xmlns:img="clr-namespace:RealEstateDemo.Images"
        xmlns:trigger="clr-namespace:RealEstateDemo.Utils.Triggers"
        Source="{img:ImageResource RealEstateDemo.Images.eye-hidden.png}">
    
    <ImageButton.Triggers>
        <EventTrigger Event="Clicked">
            <trigger:ShowPasswordTriggerAction 
                    ShowIcon="{img:ImageResource RealEstateDemo.Images.eye-show.png}"
                    HideIcon="{img:ImageResource RealEstateDemo.Images.eye-hidden.png}"
                    x:Name="ShowPasswordActualTrigger"/>
        </EventTrigger>
    </ImageButton.Triggers>
    
</ImageButton>

however every time i try to replace the original image button code with the separated one using a xmlns

  xmlns:common="clr-namespace:RealEstateDemo.Common.Views"

and

<common:PasswordToggle/>

i get No compatible code running .

System.Reflection.TargetInvocationException

Message=Exception has been thrown by the target of an invocation

i really apologize for this naive approach but am not xamarin forms expert if there is any other approach please recommend it and in general how to user reusable view (i.e grid,button,ect.). thanks in advance.

// bug full report

   android.runtime.JavaProxyThrowable: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Xamarin.Forms.Xaml.XamlParseException: Position 41:13. Can not find the object referenced by ShowPasswordActualTrigger
  at Xamarin.Forms.Xaml.ReferenceExtension.ProvideValue (System.IServiceProvider serviceProvider) [0x000db] in <804f4c0d38d4422eb26003cb4065d911>:0 
  at RealEstateDemo.View.SignInPage.InitializeComponent () [0x00fc3] in <3127c0bdd705413b88b78c5b44f792a4>:0 
  at RealEstateDemo.View.SignInPage..ctor () [0x00008] in <3127c0bdd705413b88b78c5b44f792a4>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00005] in <1b39a03c32ec46258a7821e202e0269f>:0 
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x0001d] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00095] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.RuntimeType.CreateInstanceSlow (System.Boolean publicOnly, System.Boolean wrapExceptions, System.Boolean skipCheckThis, System.Boolean fillCache) [0x00009] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.RuntimeType.CreateInstanceDefaultCtor (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Boolean wrapExceptions, System.Threading.StackCrawlMark& stackMark) [0x00027] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00020] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic) [0x00000] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at System.Activator.CreateInstance (System.Type type) [0x00000] in <1b39a03c32ec46258a7821e202e0269f>:0 
  at Xamarin.Forms.ElementTemplate+<>c__DisplayClass4_0.<.ctor>b__0 () [0x00000] in <978ec34c5c9c4c4eb3d73b6da958bcd6>:0 
  at Xamarin.Forms.ElementTemplate.CreateContent () [0x0002c] in <978ec34c5c9c4c4eb3d73b6da958bcd6>:0 
  at Xamarin.Forms.Internals.DataTemplateExtensions.CreateContent (Xamarin.Forms.DataTemplate self, System.Object item, Xamarin.Forms.BindableObject container) [0x00008] in <978ec34c5c9c4c4eb3d73b6da958bcd6>:0 
  at Xamarin.Forms.ShellContent.Xamarin.Forms.IShellContentController.GetOrCreateContent () [0x0002e] in <978ec34c5c9c4c4eb3d73b6da958bcd6>:0 
  at Xamarin.Forms.Platform.Android.ShellSectionRenderer.OnCreateView (Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState) [0x000f8] in <25214d643f8b4b97a15bcdb62359e8e5>:0 
  at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_inflater, System.IntPtr native_container, System.IntPtr native_savedInstanceState) [0x00020] in <f41f102784094fa586a15d45dcf87d88>:0 
  at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.64(intptr,intptr,intptr,intptr,intptr)
--- End of stack trace from previous location where exception was thrown ---

  at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0 
  at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00063] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0 
  at Android.App.Activity.OnStart () [0x0000a] in <db0280fb1b254cf889f3a750ac3ea0bb>:0 
  at Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnStart () [0x0001e] in <25214d643f8b4b97a15bcdb62359e8e5>:0 
  at Android.App.Activity.n_OnStart (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <db0280fb1b254cf889f3a750ac3ea0bb>:0 
  at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.14(intptr,intptr)
    at crc643f46942d9dd1fff9.FormsAppCompatActivity.n_onStart(Native Method)
    at crc643f46942d9dd1fff9.FormsAppCompatActivity.onStart(FormsAppCompatActivity.java:128)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
    at android.app.Activity.performStart(Activity.java:7252)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2970)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:1

Solution

  • The parent view does not know what ShowPasswordActualTrigger reference to as this reference in now within the custom control.

    You might want your custom control to expose a bindable property to let the parent view know weither or not you want to show password.