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?
Using the binding Glyph="{Binding Source={RelativeSource AncestorType={x:Type ButtonObject}}, Path=ButtonGlyph}"
works! Thank you @MustafaMutasim