Search code examples
buttonuicollectionviewmauiglyph

.NET MAUI Dynamically Added Button to CollectionView does not show Glyph/ImageSource


I'm using a CollectionView in .NET MAUI, in order to add Buttons dynamically, therefore being able to dynamically change the order of the buttons.

For this end, I've created a ButtonObject model:

public class ButtonObject
{
    public string? ButtonText { get; set; }
    public IRelayCommand? ButtonCommand { get; set; }
    public bool? ButtonIsVisible { get; set; }
    public string? ButtonGlyph { get; set; }

}

This model is used to create buttons for in the ViewModel:

    public partial class TestViewModel
    {
        [ObservableProperty]
        private ObservableCollection<ButtonObject> _buttons = new();
 
        private ButtonObject _testButton;

        [ObservableProperty]
        private string _testGlyph = IconFont.Add;

        public TestViewModel()
        {
            _testButton = new ButtonObject()
            {
                ButtonText = "Title",
                ButtonCommand = PerformActionCommand,
                ButtonIsVisible = true,
                ButtonGlyph = TestGlyph,
            };

            _buttons.Add(_testButton);
        }

        [RelayCommand]
        private void OnPerformAction()
        {
            //...
        }
    }

The View uses a CollectionView to display the buttons:

<CollectionView ItemsSource="{Binding Buttons}"
                ItemsLayout="HorizontalList"
                SelectionMode="None"
                ItemSizingStrategy="MeasureFirstItem">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <Grid Padding="20">
            <Button MaximumWidthRequest="150"
                    x:DataType="models:ButtonObject"
                    Text="{x:Binding ButtonText}"
                    Command="{x:Binding ButtonCommand}"
                    IsVisible="{x:Binding ButtonIsVisible}">
                <Button.ImageSource>
                    <FontImageSource FontFamily="MSO"
                                     Glyph="{x:Binding ButtonGlyph}"
                                     Size="20" />
                </Button.ImageSource>
            </Button>
        </Grid>
    </DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

However, the glyph is not visible in the CollectionView.

Regarding the icon: The ViewModel fetches the Icon information from a separate class:

public static class IconFont
{
    public const string Add = "\ue145";
    // many more...
}

And the FontFamily is from the Material Icons from Google:

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .UseMauiCommunityToolkit()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                    fonts.AddFont("MaterialIcons-Regular.ttf", "MaterialIconsRegular");
                    fonts.AddFont("MaterialSymbolsOutlined.ttf", "MSO"); // MSO = Material Symbols Outlined
                })
                .ConfigureEssentials(essentials =>
                {
                    essentials.UseVersionTracking();
                });

#if DEBUG
            builder.Logging.AddDebug();
#endif

            return builder.Build();
        }
    }
}

I've tried to use the IconFont class directly, which worked:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Project.Views.TestView"
             xmlns:helpers="clr-namespace:Project.Helpers"
             xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">

<!-- ... -->

<CollectionView ItemsSource="{Binding Buttons}"
                ItemsLayout="HorizontalList"
                SelectionMode="None"
                ItemSizingStrategy="MeasureFirstItem">
<CollectionView.ItemTemplate>
    <DataTemplate>
        <Grid Padding="20">
            <Button MaximumWidthRequest="150"
                    x:DataType="models:ButtonObject"
                    Text="{x:Binding ButtonText}"
                    Command="{x:Binding ButtonCommand}"
                    IsVisible="{x:Binding ButtonIsVisible}">
                <Button.ImageSource>
                    <FontImageSource FontFamily="MSO"
                                     Glyph="{x:Static helpers:IconFont.Add}"
                                     Size="20" />
                </Button.ImageSource>
            </Button>
        </Grid>
    </DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

</ContentPage>

Does anybody understand, why I have this odd behaviour?


Solution

  • Using the binding Glyph="{Binding Source={RelativeSource AncestorType={x:Type ButtonObject}}, Path=ButtonGlyph}" works! Thank you @MustafaMutasim