Search code examples
c#uwpuwp-xamlxbind

XamlBindingHelper Class


Can somebody provide an overview for use of the XamlBindingHelper class with examples? Specifically the GetDataTemplateComponent and SetDataTemplateComponent method.


Solution

  • In the official document, it says

    This class is for use in code that is generated by the XAML compiler.

    This tells me that I should be able to find some reference of it in code-generated classes (.g.cs) by x:Bind, given there's not a single thread on the Internet that explains what exactly it does.

    So I created a test UWP project with a ListView, and inside its ItemTemplate I threw in some x:Bind with x:Phase. After I compiled the project, I found some of its methods used inside my MainPage.g.cs -

    XamlBindingHelper.ConvertValue

    public static void Set_Windows_UI_Xaml_Controls_ItemsControl_ItemsSource(global::Windows.UI.Xaml.Controls.ItemsControl obj, global::System.Object value, string targetNullValue)
    {
        if (value == null && targetNullValue != null)
        {
            value = (global::System.Object) global::Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(global::System.Object), targetNullValue);
        }
        obj.ItemsSource = value;
    }
    

    Apparently the XamlBindingHelper.ConvertValue method is for converting values. I knew this already, as I used it in one of my recent answers on SO.


    XamlBindingHelper.SuspendRendering & XamlBindingHelper.ResumeRendering

    public int ProcessBindings(global::Windows.UI.Xaml.Controls.ContainerContentChangingEventArgs args)
    {
        int nextPhase = -1;
        switch(args.Phase)
        {
            case 0:
                nextPhase = 1;
                this.SetDataRoot(args.Item);
                if (!removedDataContextHandler)
                {
                    removedDataContextHandler = true;
                    ((global::Windows.UI.Xaml.Controls.StackPanel)args.ItemContainer.ContentTemplateRoot).DataContextChanged -= this.DataContextChangedHandler;
                }
                this.initialized = true;
                break;
            case 1:
                global::Windows.UI.Xaml.Markup.XamlBindingHelper.ResumeRendering(this.obj4);
                nextPhase = -1;
                break;
        }
        this.Update_((global::System.String) args.Item, 1 << (int)args.Phase);
        return nextPhase;
    }
    
    public void ResetTemplate()
    {
        this.bindingsTracking.ReleaseAllListeners();
        global::Windows.UI.Xaml.Markup.XamlBindingHelper.SuspendRendering(this.obj4);
    }
    

    XamlBindingHelper.SuspendRendering & XamlBindingHelper.ResumeRendering look very interesting. They seem to be the key functions to enable ListView/GridView's incremental item rendering which helps improve the overall panning/scrolling experience.

    So apart from x:DeferLoadingStrategy and x:Load(Creators Update), they are something else that could be used to improve your app performance.


    IDataTemplateComponent & IDataTemplateExtension

    However, I couldn't find anything related to GetDataTemplateComponent and SetDataTemplateComponent. I even tried to manually set this attached property in XAML but the get method always returned null.

    And here's the interesting bit. I later found this piece of code in the generated class.

    case 2: // MainPage.xaml line 13
        {                    
            global::Windows.UI.Xaml.Controls.Grid element2 = (global::Windows.UI.Xaml.Controls.Grid)target;
            MainPage_obj2_Bindings bindings = new MainPage_obj2_Bindings();
            returnValue = bindings;
            bindings.SetDataRoot(element2.DataContext);
            element2.DataContextChanged += bindings.DataContextChangedHandler;
            global::Windows.UI.Xaml.DataTemplate.SetExtensionInstance(element2, bindings);
        }
        break;
    

    The method DataTemplate.SetExtensionInstance looks very similar to XamlBindingHelper.SetDataTemplateComponent. It takes element2 which is the root Grid inside the ItemTemplate of my ListView, and an IDataTemplateExtension; where the latter takes an element and an IDataTemplateComponent. If you have a look at their definitions, their functionalities are very similar, which makes me think if DataTemplate.SetExtensionInstance is the replacement of XamlBindingHelper.SetDataTemplateComponent? I'd love to know if otherwise.

    Unlike IDataTemplateComponent, you can get an instance of the IDataTemplateExtension in your code -

    var firstItemContainer = (ListViewItem)MyListView.ContainerFromIndex(0);
    var rootGrid = (Grid)firstItemContainer?.ContentTemplateRoot;
    var dataTemplateEx = DataTemplate.GetExtensionInstance(rootGrid);
    

    In my case, the dataTemplateEx is an instance of another generated class called MainPage_obj2_Bindings, where you have access to methods like ResetTemplate and ProcessBindings.

    I assume they could be helpful if you were to build your own custom list controls, but other than that I just can't see why you would ever need them.