Skip to content

Add New Enum Description Converter#3137

Open
BillyMartin1964 wants to merge 20 commits intoCommunityToolkit:mainfrom
BillyMartin1964:main
Open

Add New Enum Description Converter#3137
BillyMartin1964 wants to merge 20 commits intoCommunityToolkit:mainfrom
BillyMartin1964:main

Conversation

@BillyMartin1964
Copy link

This converter converts Enum values into readable text so they display nicely in the UI. When an Enum value is passed in, the converter looks for attributes that provide a more user-friendly name. If one is found, it uses that value; otherwise it simply uses the Enum’s name. This ensures that Enum values can be displayed clearly while still working correctly even when no attributes are defined. Unit tests are included to verify the expected behavior.

Description of Change

Added new converter

Linked Issues

  • Fixes #

PR Checklist

Additional information

Example use case:

 Text="{Binding SelectedModeName, Converter={StaticResource EnumDescriptionConverter}}"

public enum ModeName
{
    [Display(Name = "Light  Mode")]
    LightMode,
    [Display(Name = "Dark  Mode")]
    DarkMode,
    [Display(Name = "System")]
    System
}

This converter transforms Enum values into strings by checking for DisplayAttribute or DescriptionAttribute. It prioritizes the Name property of DisplayAttribute, then the Description property of DescriptionAttribute, and finally falls back to the Enum's string representation. Unit tests are included to verify attribute precedence, whitespace handling, and fallback behavior.
Copilot AI review requested due to automatic review settings March 10, 2026 06:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new value converter to the CommunityToolkit.Maui converters set to turn Enum values into user-friendly strings for UI display, with unit tests validating expected attribute precedence and fallbacks.

Changes:

  • Introduces EnumDescriptionConverter that prefers DisplayAttribute, then DescriptionAttribute, then falls back to Enum.ToString().
  • Adds unit tests covering attribute precedence and fallback behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/CommunityToolkit.Maui/Converters/EnumDescriptionConverter.cs New converter for mapping enum values to display-friendly strings via attributes.
src/CommunityToolkit.Maui.UnitTests/Converters/EnumDescriptionConverterTests.cs Unit tests for the new converter’s attribute selection and fallback logic.

@BillyMartin1964
Copy link
Author

There is a PR for the documentation at:

MicrosoftDocs/CommunityToolkit#622

The converter now uses the GetName method on DisplayAttribute to retrieve localized strings when a ResourceType is provided. It includes fallback logic for cases where the resource is missing, the display name is whitespace, or the GetName method throws an exception. New unit tests verify these localization scenarios and edge cases for both DisplayAttribute and DescriptionAttribute.
Update EnumDescriptionConverterTests to inherit from BaseOneWayConverterTest to align with standard value converter tests.
Update the ConvertFrom_ThrowsArgumentNullException_WhenNull test in EnumDescriptionConverterTests.cs to cast the converter to ICommunityToolkitValueConverter and invoke the Convert method.
@BillyMartin1964
Copy link
Author

BillyMartin1964 commented Mar 10, 2026 via email

Copy link
Collaborator

@TheCodeTraveler TheCodeTraveler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @BillyMartin1964.

I'm a bit confused by the scope of this Converter and would like to avoid using Reflection.

Scope

Does it get the DescriptionAttribute or does it get DisplayAttribute.Name?

To put yourself in another developer's shoes, if you saw a converter named EnumDescriptionConverter as you're scrolling through intellisense, what would you assume it would do? Devs don't always read docs, so naming + scope is critically important.

It's named the EnumDescriptionConverter which implies it will return the DescriptionAttribute, but this current implementation may return three different results without providing any control to the developer over which results comes back:

  • DescriptionAttribute
  • DisplayAttribute.Name
  • Enum name

We should not return the enum name as that will cause confusion to the developer who expected its description. Instead, it should return null to indicate to the developer that no attribute was found, or throw an InvalidOperationException if we decide this converter does not support enums without descriptions.

After that fix, I see two paths forward for this new converter:

  1. Separate this into two separate converters:
    • EnumDescriptionConverter : BaseConverterOneWay<Enum, string?>
    • EnumDisplayNameConverter : BaseConverterOneWay<Enum, string?>
  2. Create an enum that allows the developer to choose which value is returned
  • This would be similar to our implementation for the CompareConverter StringToListConverter and how it allows developers customization via its enum OperatorType

Reflection

I don't love that the current implementation is using reflection which limits the abilities for AOT compiling. Is this possible without Reflection?

Have you confirmed this runs works on an iOS Device built in Release configuration without the Mono Interpreter? And have you confirmed this works in an AOT'd code base?

New Feature Proposal Process

In the future, before submitting a PR implementing a feature and before writing the docs for it, I recommend following our process for Submitting a New Feature . You've skipped the Proposal phase where we would've had this discussion about its implementation and saved time and re-work.

public partial class EnumDescriptionConverter : BaseConverterOneWay<Enum, string>
{
/// <inheritdoc/>
public override string DefaultConvertReturnValue { get; set; } = string.Empty;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public override string DefaultConvertReturnValue { get; set; } = string.Empty;
public override string? DefaultConvertReturnValue { get; set; }

It would make sense for this converter to return a nullable string and return null when an enum does not contain a Description attribute.

/// Converts an <see cref="Enum"/> value to its display string using <see cref="DisplayAttribute"/> or <see cref="DescriptionAttribute"/>.
/// </summary>
[AcceptEmptyServiceProvider]
public partial class EnumDescriptionConverter : BaseConverterOneWay<Enum, string>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public partial class EnumDescriptionConverter : BaseConverterOneWay<Enum, string>
public partial class EnumDescriptionConverter : BaseConverterOneWay<Enum, string?>

It would make sense for this converter to return a nullable string, BaseConverterOneWay<Enum, string?> and return null when an enum does not contain a Description attribute.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had a null return, but the copilots reviewer said we should return the key if the user was localizing. What do you think?

/// otherwise the value of the <see cref="DescriptionAttribute.Description"/> if defined;
/// otherwise the enum name as a string.
/// </returns>
public override string ConvertFrom(Enum value, CultureInfo? culture = null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public override string ConvertFrom(Enum value, CultureInfo? culture = null)
public override string? ConvertFrom(Enum value, CultureInfo? culture = null)

It would make sense for this converter to return a nullable string and return null when an enum does not contain a Description attribute.

return descriptionAttr.Description;
}

return value.ToString(); // Fallback to enum name if no attribute found
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return value.ToString(); // Fallback to enum name if no attribute found
return value.ToString(); // Fallback to enum name if no attribute found

It would make sense for this converter to return a nullable string and return null when an enum does not contain a Description attribute.

@TheCodeTraveler TheCodeTraveler added the needs discussion Discuss it on the next Monthly standup label Mar 10, 2026
@BillyMartin1964
Copy link
Author

BillyMartin1964 commented Mar 10, 2026

I wrote this converter for my own use, when I realized there wasn't one in the toolkit. It's really quite handy, and I thought I would share it with the community. I did open a discussion, and asked James Montemagno to champion it, but he said to just send the pull request.

Here's the discussion link:

#3136

I don't really see the problem with a tiny converter. I tried to cover all the bases. Some devs use display name, some use description, and some use localization. We could make three converters if you want.

It really doesn't matter to me as long as it ends up in the toolkit. I think it's quite a useful converter. Also, if you want to finish it up, that's fine too. Just let me know. Happy to help.

@BillyMartin1964
Copy link
Author

We should not return the enum name as that will cause confusion to the developer who expected its description. Instead, it should return null to indicate to the developer that no attribute was found, or throw an InvalidOperationException if we decide this converter does not support enums without descriptions.

I'm not sure that you are right on this one. I usually don't put descriptions for one-word enum members.

This commit introduces an EnumDescriptionConverter that transforms Enum values into strings. It first checks for the DisplayAttribute, then the DescriptionAttribute. The conversions prioritize localized strings from DisplayAttribute based on a provided ResourceType. If unavailable or blank, it falls back to the DescriptionAttribute's Description property, and finally to the Enum's string representation. Unit tests ensure attribute precedence, whitespace handling, and fallback logic are working correctly.
This commit introduces an EnumDescriptionConverter that transforms Enum values into strings. It prioritizes the Name property of DisplayAttribute or the Description property of DescriptionAttribute, and falls back to the Enum's string representation. Unit tests verify attribute precedence, whitespace handling, and fallback behavior.
@BillyMartin1964
Copy link
Author

Sample app page is completed. Works fine without reflection.

image

…g adjustments

This commit updates the EnumDescriptionConverterPage.xaml to enhance the visual presentation of labels for Enum modes. It modifies the border elements, increases padding, applies a light gray background, and introduces a RoundRectangle stroke shape. Additionally, label text colors for 'Without Converter' and 'With Converter' sections are set to dark red for better contrast and readability.
TheCodeTraveler and others added 6 commits March 11, 2026 13:23
Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>
This commit enhances the user interface of EnumDescriptionConverter by adjusting styles and spacing for better presentation of enum modes. Modifications include increased border width, added padding, application of a light gray background, and introduction of a RoundRectangle stroke for border elements. The contrast of 'Without Converter' and 'With Converter' section labels is improved through coloring the text in dark red.
This commit enhances EnumDescriptionConverter`s user interface by adjusting styles and spacing for better presentation of enum modes. Modifications include increased border width, added padding, application of a light gray background, and introduction of a RoundRectangle stroke for border elements. The contrast of 'Without Converter' and 'With Converter' section labels is improved through coloring the text in dark red.
The code has been altered to avoid reflection when checking for the presence of an Enum description attribute. Previously, the check used reflection with `getAttribute` to ensure the attribute's class matched `descriptionAttributeName`, which has been replaced with a direct null and length check on `descAttr`.
@BillyMartin1964
Copy link
Author

Works great in debug, but crashing immediately in release. I think it may be my profiles. Can one of you try it in release mode, please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs discussion Discuss it on the next Monthly standup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants