Articles in this section
Category / Section

How to customize the expander view when loading on demand in Xamarin.Forms TreeView (SfTreeView)

2 mins read

You can customize the load indicator by using the custom expander icon and SfBusyIndicator in Xamarin.Forms SfTreeView. Also, you can customize the load indicator based on level.

You can refer to the following document regarding custom expander icon,

https://www.syncfusion.com/kb/10289/how-to-expand-and-collapse-treeview-node-using-image-instead-expander

XAML: Expander View – BusyIndicator as load indicator and Image as expander icon

Load custom expander icon and BusyIndicator in the same column and change the visibility based on the TreeViewNode properties using Converters.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TreeViewXamarin"
             xmlns:treeview="clr-namespace:Syncfusion.XForms.TreeView;assembly=Syncfusion.SfTreeView.XForms"
             xmlns:sfbusyindicator="clr-namespace:Syncfusion.SfBusyIndicator.XForms;assembly=Syncfusion.SfBusyIndicator.XForms"
             x:Class="TreeViewXamarin.MainPage" Padding="0,20,0,0">
    <ContentPage.BindingContext>
        <local:MusicInfoRepository x:Name="viewModel"/>
    </ContentPage.BindingContext>
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:ExpanderIconVisibilityConverter x:Key="ExpanderIconVisibilityConverter"/>
            <local:ExpanderIconConverter x:Key="ExpanderIconConverter" />
            <local:IndicatorColorConverter x:Key="IndicatorColorConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Behaviors>
        <local:Behavior/>
    </ContentPage.Behaviors>
    <ContentPage.Content>
        <treeview:SfTreeView x:Name="treeView" ExpanderWidth="0" ItemTemplateContextType="Node" LoadOnDemandCommand="{Binding TreeViewOnDemandCommand}" ItemsSource="{Binding Menu}">
            <treeview:SfTreeView.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="grid" Padding="5,5,5,5" BackgroundColor="White">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid Grid.Column="1" Padding="1,0,0,0" VerticalOptions="Center">
                            <Label LineBreakMode="NoWrap" TextColor="Black" Text="{Binding Content.ItemName}" FontSize="20" VerticalTextAlignment="Center"/>
                        </Grid>
                        <Grid >
                            <Image Source="{Binding IsExpanded, Converter={StaticResource ExpanderIconConverter}}"
                                   IsVisible="{Binding HasChildNodes, Converter={StaticResource ExpanderIconVisibilityConverter}}"
                                   VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="35" WidthRequest="35">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
                                </Image.GestureRecognizers>
                            </Image>
                            <Grid IsVisible="{Binding Content.IsInAnimation, Mode=TwoWay}">
                                <sfbusyindicator:SfBusyIndicator x:Name="grid1" TextColor="{Binding Level, Converter={StaticResource IndicatorColorConverter}}" 
                                                                 IsBusy="True" Margin="2" BackgroundColor="White" ViewBoxHeight="25" ViewBoxWidth="25" HeightRequest="32" AnimationType="SingleCircle"/>
                            </Grid>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </treeview:SfTreeView.ItemTemplate>
        </treeview:SfTreeView>
    </ContentPage.Content>
</ContentPage>

C#: Handled the BusyIndicator visibility based on the IsInAnimation model property

Update the IsInAnimation property in the LoadOnDemandCommand execution method.

namespace TreeViewXamarin
{
    public class MusicInfoRepository
    {
        public ICommand TreeViewOnDemandCommand{ get; set; }
 
        public MusicInfoRepository()
        {
            TreeViewOnDemandCommand = new Command(ExecuteOnDemandLoading, CanExecuteOnDemandLoading);
        }
 
        private bool CanExecuteOnDemandLoading(object sender)
        {
            var hasChildNodes = ((sender as TreeViewNode).Content as MusicInfo).HasChildNodes;
            if (hasChildNodes)
                return true;
            else
                return false;
        }
 
        private void ExecuteOnDemandLoading(object obj)
        {
            var node = obj as TreeViewNode;
 
            // Skip the repeated population of child items when every time the node expands.
            if (node.ChildNodes.Count > 0)
            {
                node.IsExpanded = true;
                return;
            }
 
            MusicInfo musicInfo = node.Content as MusicInfo;
            musicInfo.IsInAnimation = true;
 
            Device.BeginInvokeOnMainThread(async () =>
            {
                await Task.Delay(500);
                var items = GetSubMenu(musicInfo.ID);
                // Populating child items for the node in on-demand
                node.PopulateChildNodes(items);
                if (items.Count() > 0)
                    node.IsExpanded = true;
 
                musicInfo.IsInAnimation = false;
            });
        }
    }
}

C#

The expander icon visibility is handled based on the HasChildNodes.

namespace TreeViewXamarin
{
    public class ExpanderIconVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (!(bool)value) ? false : true;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
}

C#: Load indicator color customization

Converter to customize the load indicator color based on the TreeViewNode.Level property.

namespace TreeViewXamarin
{
    public class IndicatorColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (int)value == 0 ? Color.Red : Color.Green;
        }
    }
}

Output

Demo image to use custom load indicator in Xamarin.Forms SfTreeView

View sample in GitHub

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied