Load Xaml Dynamically At Runtime

MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
edited February 2017 in Xamarin.Forms

Everybody knows that this is an absolute necessity. Everybody is howling about this, and has been for years. However, it still seems as though it is impossible, through normal means to render Xamarin Forms UI at runtime with dynamic Xaml. I'm not really interested in why this hasn't been done yet. What I want to know is WHEN is it going to be done? And, if there is no answer to that, how do we work around this gaping, chasm of a deficiency?

As I see it, there may be two possible approaches to working around this disgusting, blatant inadequacy:

1) Write a Xaml parser that dynamically builds objects and sets their bindings programmatically. This will be hard work, and I don't have time to be doing this. Has anyone else started an open source project to try to achieve this?

2) Take the internal XamlLoader (https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Xaml/XamlLoader.cs) code, and make a version which is public. Has anyone had any luck doing this?

Note: incidentally, you can see the code for the XamlLoader here: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Xaml/XamlLoader.cs . There doesn't seem to be an explanation for why this class is not public.

Best Answers

  • MelbourneDeveloperMelbourneDeveloper AU ✭✭✭
    edited February 2017 Accepted Answer

    In short, my problem has been successfully worked around. But, a) I have not tested this code in all scenarios. And, b) the next guy who wants to do what I want to do will be asking exactly the same question because as you can see from the code above, the Xamarin Forms team have inexplicably left the "LoadFromXaml" method, and the "XamlLoader" class internal. So, as @NMackay pointed out, I have created a thread on the Xamarin.Forms Evolution board here:

    https://forums.xamarin.com/discussion/87810/please-make-xamlloader-public

    If you are reading this and want to achieve the same result as us, please take the time to put your comments on this thread and request that the Xamarin Forms team make the method public.

  • MelbourneDeveloperMelbourneDeveloper AU ✭✭✭
    edited July 2017 Accepted Answer

    I have been working on a library and I have included dynamic rendering of XAML. According to the Xamarin Forms team, they are not intending on disabling the dynamic functionality so I think you would be safe to use this. Clone this repo to see the sample:

    https://github.com/MelbourneDeveloper/Adapt.Presentation.git

Answers

  • NMackayNMackay GBInsider, University mod

    I'd post this on the evolution forum, if you post it here it'll just fall away and not get attention. Follow the posting guidelines though or it will be removed.

    https://forums.xamarin.com/categories/xamarin-forms-evolution

    I was looking into this recently but opted for loading contentviews into a viewcell in a LIstview (RadListview in my case but it works with vanilla listview too) and a bit of Prism magic to autowize the contentview's to the correct binding context. This way I can build teh users dashboard based on their security rights.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    I have half an answer. This article provides some kind of workaround:
    http://www.cazzulino.com/dynamic-forms.html

    The writer of this article has provided his code here:
    https://github.com/MobileEssentials/DynamicForms/blob/master/src/Xamarin.Forms.Dynamic.Desktop/BindingObjectExtensions.cs#L38

    I modified this code slightly to make it less ugly and more like Silverlight/WPF/UWP:

    public static class XamlReader
    {
        static Func<BindableObject, string, BindableObject> loadXaml;
    
        static XamlReader()
        {
            // This is the current situation, where the LoadFromXaml is the only non-public static method.
            var genericMethod = typeof(Xamarin.Forms.Xaml.Extensions)
                .GetMethods(BindingFlags.Static | BindingFlags.NonPublic).FirstOrDefault();
    
            // If we didn't find it, it may be because the extension method may be public now :)
            if (genericMethod == null)
                genericMethod = typeof(Xamarin.Forms.Xaml.Extensions)
                .GetMethods(BindingFlags.Static | BindingFlags.Public)
                .FirstOrDefault(m => m.GetParameters().Last().ParameterType == typeof(string));
    
            if (genericMethod == null)
            {
                loadXaml = (view, xaml) => { throw new NotSupportedException("Xamarin.Forms implementation of XAML loading not found. Please update the Dynamic nuget package."); };
            }
            else
            {
                genericMethod = genericMethod.MakeGenericMethod(typeof(BindableObject));
                loadXaml = (view, xaml) => (BindableObject)genericMethod.Invoke(null, new object[] { view, xaml });
            }
        }
    
        /// <summary>
        /// Applies the given XAML to the view.
        /// </summary>
        private static TView LoadFromXaml<TView>(this TView view, string xaml) where TView : BindableObject
        {
            return (TView)loadXaml(view, xaml);
        }
    
        /// <summary>
        /// Applies the given XAML to the view.
        /// </summary>
        public static TView LoadFromXaml<TView>(string xaml) where TView : BindableObject
        {
            var theView = (TView)Activator.CreateInstance(typeof(TView));
            return LoadFromXaml(theView, xaml);
        }
    
    }
    
  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
    edited February 2017 Accepted Answer

    In short, my problem has been successfully worked around. But, a) I have not tested this code in all scenarios. And, b) the next guy who wants to do what I want to do will be asking exactly the same question because as you can see from the code above, the Xamarin Forms team have inexplicably left the "LoadFromXaml" method, and the "XamlLoader" class internal. So, as @NMackay pointed out, I have created a thread on the Xamarin.Forms Evolution board here:

    https://forums.xamarin.com/discussion/87810/please-make-xamlloader-public

    If you are reading this and want to achieve the same result as us, please take the time to put your comments on this thread and request that the Xamarin Forms team make the method public.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    The Xamarin Forms team eventually closed this topic...

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
    edited July 2017 Accepted Answer

    I have been working on a library and I have included dynamic rendering of XAML. According to the Xamarin Forms team, they are not intending on disabling the dynamic functionality so I think you would be safe to use this. Clone this repo to see the sample:

    https://github.com/MelbourneDeveloper/Adapt.Presentation.git

  • DamianSuessDamianSuess USMember ✭✭

    @MelbourneDeveloper said:
    I have been working on a library and I have included dynamic rendering of XAML. According to the Xamarin Forms team, they are not intending on disabling the dynamic functionality so I think you would be safe to use this. Clone this repo to see the sample:

    https://github.com/MelbourneDeveloper/Adapt.Presentation.git

    I assume this has been taken down since then? Was looking forward to seeing your example

Sign In or Register to comment.