⮪ Setting Entry Images

July 20, 2024 · View on GitHub

Once you've setup your DonutChartView there's a property called EntryImageTemplate that you can populate to render icons for each entry. This property expects a DataTemplate that creates a FileImageSource.

Static Image

So if your MAUI project had an image file called baseball.png, to render every entry with that image you'd populate the property as follows:

XAML

<donut:DonutChartView.EntryImageTemplate>
    <DataTemplate>
        <FileImageSource File="baseball.png" />
    </DataTemplate>
</donut:DonutChartView.EntryImageTemplate>

Code-Behind

static object LoadEntryIcon()
{
    return ImageSource.FromFile("baseball.png");
}

MyChartView.EntryImageTemplate = new DataTemplate(LoadEntryIcon);

Which might look something like this:

Example Image #1

Note

If your images are rendering too large or too small, set the EntryImageScale on your DonutChartView accordingly.

Dynamic Image

In most scenarios you're going to want to set each entry's image depending on a condition. To allow for this the EntryImageTemplate that you set is provided the original entry object as its binding context, meaning you can handle the image selection however you'd like. However, here's two common approaches.

Value Converters

In this scenario, we bind to a property called Category on the TestResult model which is an enum. Then we use a binding value converter to convert the TestResult's Category to the image file we want to display. Below is the IValueConverter we'll use to do the conversion.

public class ResultCategoryImageConverter : IValueConverter
{
    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        if (value is not ResultCategory category)
        {
            return FasIcons.ScrollFile;
        }

        return category switch
        {
            ResultCategory.English => FasIcons.CommentFile,
            ResultCategory.Mathematics => FasIcons.CalculatorFile,
            ResultCategory.Science => FasIcons.FlaskFile,
            ResultCategory.Geography => FasIcons.BookAtlasFile,
            ResultCategory.Technology => FasIcons.MicrochipFile,
            ResultCategory.Sports => FasIcons.BaseballFile,
            ResultCategory.Music => FasIcons.MusicFile,
            ResultCategory.Drama => FasIcons.MaskFile,
            ResultCategory.Languages => FasIcons.GlobeFile,
            _ => FasIcons.ScrollFile
        };
    }

    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML

<donut:DonutChartView.EntryImageTemplate>
    <DataTemplate x:DataType="m:TestResult">
        <FileImageSource File="{Binding Category, Converter={StaticResource ResultCategoryImageConverter}}" />
    </DataTemplate>
</donut:DonutChartView.EntryImageTemplate>

Code-Behind

static object LoadEntryIcon()
{
    FileImageSource imageSource = new();
    Binding categoryBinding = new(
        path: nameof(TestResult.Category),
        converter: new ResultCategoryImageConverter());
    imageSource.SetBinding(FileImageSource.FileProperty, categoryBinding);
    return imageSource;
}

MyChartView.EntryImageTemplate = new DataTemplate(LoadEntryIcon);

Properties

In this scenario, we bind to a expression body property called ImagePath on the TestResult model which is a string. When you access this property it executes a method that returns the path of the image depending on the TestResult's Category property.

TestResult.cs

public class TestResult
{
    public ResultCategory Category { get; set; }
    public string FilePath => GetFilePath();

    private string GetFilePath()
    {
        return Category switch
        {
            ResultCategory.English => FasIcons.CommentFile,
            ResultCategory.Mathematics => FasIcons.CalculatorFile,
            ResultCategory.Science => FasIcons.FlaskFile,
            ResultCategory.Geography => FasIcons.BookAtlasFile,
            ResultCategory.Technology => FasIcons.MicrochipFile,
            ResultCategory.Sports => FasIcons.BaseballFile,
            ResultCategory.Music => FasIcons.MusicFile,
            ResultCategory.Drama => FasIcons.MaskFile,
            ResultCategory.Languages => FasIcons.GlobeFile,
            _ => FasIcons.ScrollFile
        };
    }
}

XAML

<donut:DonutChartView.EntryImageTemplate>
    <DataTemplate x:DataType="m:TestResult">
        <FileImageSource File="{Binding FilePath}" />
    </DataTemplate>
</donut:DonutChartView.EntryImageTemplate>

Code-Behind

static object LoadEntryIcon()
{
    FileImageSource imageSource = new();
    Binding filePathBinding = new(path: nameof(TestResult.FilePath));
    imageSource.SetBinding(FileImageSource.FileProperty, filePathBinding);
    return imageSource;
}

MyChartView.EntryImageTemplate = new DataTemplate(LoadEntryIcon);

Your images might look something like this:

Example Image #2

Note

If your images are rendering too large or too small, set the EntryImageScale on your DonutChartView accordingly.