Xamarin.Forms: Pass Enum Parameter to URL with Type Converter

71 Views Asked by At

In my page I have a Binding Property of enum type:

[QueryProperty(nameof(EnumProp), nameof(EnumProp))]
public partial class MyPage : ContentPage
{
    public static readonly BindableProperty EnumPropProperty =
       BindableProperty.Create(nameof(EnumProp), typeof(MyEnum), typeof(MyPage), propertyChanged: OnEnumPropChanged);

    public MyEnum EnumProp
    {
        get => (MyEnum)GetValue(EnumPropProperty);
        set => SetValue(EnumPropProperty, value);
    }

I would like to call this page by GoToAsync:

        MyEnum enumProp = MyEnum.ThisValue;
        string dest = $"{nameof(MyPage)}?{nameof(MyPage.EnumProp)}={enumProp}";
        await Shell.Current.GoToAsync(dest);

In my example, dest is "MyPage?EnumProp=ThisValue" and GoToAsync throws InvalidCastException.

So I added a TypeConverter to property EnumProp:

    [TypeConverter(typeof(StringToEnumConverter<MyEnum>))]
    public MyEnum EnumProp

First I implemented StringToEnumConverter<T> derived from Xamarin.Forms.TypeConverter then I implemented interface IValueConverter. In both cases InvalidCastException is thrown:

Edit: Stack Trace is as follows:

System.InvalidCastException
  HResult=0x80004002
  Nachricht = Invalid cast from 'System.String' to 'XXX.MyEnum'.
  Quelle = System.Private.CoreLib
  Stapelüberwachung:
   bei System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   bei Xamarin.Forms.ShellContent.ApplyQueryAttributes(Object content, IDictionary`2 query, IDictionary`2 oldQuery)
   bei Xamarin.Forms.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
   bei Xamarin.Forms.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess)
   bei Xamarin.Forms.ShellNavigationManager.ApplyQueryAttributes(Element element, IDictionary`2 query, Boolean isLastItem, Boolean isPopping)
   bei Xamarin.Forms.ShellSection.<GoToAsync>d__69.MoveNext()
   bei Xamarin.Forms.ShellNavigationManager.<GoToAsync>d__13.MoveNext()
   bei XXX.MyPage.<ToDetail>d__17.MoveNext() in C:\Users\MyUser\Development\...\PackObjectItem.cs: Zeile46

End Edit

What is to do in my case?

2

There are 2 best solutions below

0
Jessie Zhang -MSFT On BEST ANSWER

You can convert the data to a string type and pass it through.

Please refer to the following code:

[QueryProperty(nameof(EnumProp), nameof(EnumProp))]
public partial class MyPage : ContentPage
{

    public MyPage()
    {
        InitializeComponent();
    }

    public string EnumProp
    {
        set
        {
            LoadData(value);
        }
    }

    private void LoadData(string value)
    {
        System.Diagnostics.Debug.WriteLine("the passed data is " + value);

        Title = "---> "+value;
    }
 }

Then you can pass data as follows:

  MyEnum enumProp = MyEnum.Spring;

 await Shell.Current.GoToAsync($"mypage?EnumProp={enumProp.ToString()}");  

Note

1.the string mypage is the route of page MyPage

        Routes.Add("mypage", typeof(MyPage));

2.the code of MyEnum.cs is:

public enum MyEnum
{
    Spring,
    Summer,
    Autumn,
    Winter
}
0
Bernd Morgeneyer On

Ok, that is exactly what I decided to do. I hoped that there is a more elegant solution.

So this is my workaround:

[QueryProperty(nameof(EnumPropS), nameof(EnumProp))]
public partial class MyPage : ContentPage
{
    public static readonly BindableProperty EnumPropProperty =
       BindableProperty.Create(nameof(EnumProp), typeof(MyEnum), typeof(MyPage), propertyChanged: OnEnumPropChanged);

    public MyEnum EnumProp
    {
        get => (MyEnum)GetValue(EnumPropProperty);
        set => SetValue(EnumPropProperty, value);
    }

    // Additional property for queries:
    public string EnumPropS
    {
        get => EnumProp.ToString();
        set => EnumProp = (MyEnum)Enum.Parse(typeof(MyEnum), value);
    }

The query looks exactly as in my question above.