0

I have the following lines of XAML that utilises Native Views in Xamarin Forms:

        <androidWidget:RadioGroup x:Arguments="{x:Static formsAndroid:Forms.Context}">
            <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Click="RadioButton1Clicked"/>
            <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Click="RadioButton2Clicked"/>
            <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Click="RadioButton3Clicked"/>
            <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Click="RadioButton4Clicked"/>
        </androidWidget:RadioGroup>

However, the following exception is thrown: "Can not set the content of androidWidget:RadioGroup as it doesn't have a ContentPropertyAttribute"

Just wondering if anyone could help me find the correct XAML layout for the RadioGroup in relation to the RadioButtons?

Cheers

Elvis Xia - MSFT
  • 10,801
  • 1
  • 13
  • 24
hlbmallo
  • 151
  • 2
  • 12

1 Answers1

3

However, the following exception is thrown: "Can not set the content of androidWidget:RadioGroup as it doesn't have a ContentPropertyAttribute"

Not all native views can be used in xaml directly. RadioGroup is one of them.

To use it in your Xaml, you need to follow the below steps:

  1. In YourProject.Droid create a custom RadioGroup control:

    public class MyRadioGroup:RadioGroup
    {
        //Every native control in xaml will be wrapped in NativeViewWrapper, so we want to pass a NativeViewWrapper list here
        IList<NativeViewWrapper> items;
        public IList<NativeViewWrapper> ItemsSource
        {
            get {
                items.Clear();
                for (int i = 0; i < this.ChildCount; i++)
                {
                    items.Add(new NativeViewWrapper(this.GetChildAt(i)));
                }
                return items;
            }
            set {
                //xaml compiler will call this setter
                if (items != value)
                {
                    items = value;
                    this.RemoveAllViews();
                    foreach (NativeViewWrapper wrapper in items)
                    {
                        this.AddView(wrapper.NativeView);
                    }
                }
            }
        }
        public MyRadioGroup(Context context) : base(context)
        {
            items = new List<NativeViewWrapper>();
        }
    }
    
  2. In your pcl library add necessary namespaces:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            ...
            xmlns:androidWrapper="clr-namespace:Xamarin.Forms.Platform.Android;assembly=Xamarin.Forms.Platform.Android;targetPlatform=Android"
            xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
            xmlns:androidLocal="clr-namespace:NativeSwitch.Droid;assembly=NativeSwitch.Droid;targetPlatform=Android"
            xmlns:formsAndroid="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.Platform.Android;targetPlatform=Android"
    xmlns:local="clr-namespace:NativeSwitch"
    ...">
    
  3. Reference the custom MyRadioGroup in your xaml page:

    <StackLayout Margin="20">
        <androidLocal:MyRadioGroup x:Arguments="{x:Static formsAndroid:Forms.Context}" >
            <androidLocal:MyRadioGroup.ItemsSource>
                <x:Array Type="{x:Type androidWrapper:NativeViewWrapper}">
                    <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Text="Scale1" />
                    <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Text="Scale2" />
                    <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Text="Scale3" />
                    <androidWidget:RadioButton x:Arguments="{x:Static formsAndroid:Forms.Context}" Text="Scale4" />
                </x:Array>
            </androidLocal:MyRadioGroup.ItemsSource>
        </androidLocal:MyRadioGroup>
    </StackLayout>
    

You can find a complete demo here.

For similar official tutorial, please refer to Subclassing Native Views

For passing arguments inside Xaml, please refer to Passing Arguments in Xaml

Elvis Xia - MSFT
  • 10,801
  • 1
  • 13
  • 24
  • Thanks for your answer. I followed your instructions but now I get the following exception: Xamarin.Forms.Xaml.XamlParseException: Position 13:18. Type androidLocal:MyRadioGroup not found in xmlns clr-namespace:MyProject.Droid;assembly=MyProject.Droid;targetPlatform=Android Would you have any advice on how to get round this? – hlbmallo Jan 16 '18 at 23:57
  • Please replace "MyProject" to your project name. For example, if your project name is `NativeViewSample`, then you need to change `MyProject.Droid` to `NativeViewSample.Droid`. – Elvis Xia - MSFT Jan 17 '18 at 00:38
  • I tried this out but the exception is still throwing, even after the solution has been cleaned and rebuilt. Just wondering if the fact that the MyProjectName.Droid namespace isn't showing up in Intellisense in the PCL project is relevant? – hlbmallo Jan 17 '18 at 09:38
  • There is no Intellisense support for that namespace define. You have to check the spell of the namespace yourself. You can try uninstall and reinstall the app in your emulator/device. if the problem persists, you can share your project through online repo. Or compare with my posted demo to figure out the mistake – Elvis Xia - MSFT Jan 17 '18 at 10:00
  • Managed to get the code to run without throwing the exception in my project. The issue revolved around my project assembly name being MyProjectName.Android instead of MyProjectName.Droid. When I changed it to .Droid, it worked like a charm. Thanks for your advice and code @Elvis Xia – hlbmallo Jan 19 '18 at 13:21