Add New Enum Description Converter#3137
Add New Enum Description Converter#3137BillyMartin1964 wants to merge 8 commits intoCommunityToolkit:mainfrom
Conversation
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.
There was a problem hiding this comment.
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
EnumDescriptionConverterthat prefersDisplayAttribute, thenDescriptionAttribute, then falls back toEnum.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. |
src/CommunityToolkit.Maui/Converters/EnumDescriptionConverter.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui/Converters/EnumDescriptionConverter.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.UnitTests/Converters/EnumDescriptionConverterTests.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.UnitTests/Converters/EnumDescriptionConverterTests.cs
Outdated
Show resolved
Hide resolved
|
There is a PR for the documentation at: |
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.
|
@dotnet-policy-service agree
…________________________________
From: dotnet-policy-service[bot] ***@***.***>
Sent: Tuesday, March 10, 2026 3:26 AM
To: CommunityToolkit/Maui ***@***.***>
Cc: Billy Martin ***@***.***>; Mention ***@***.***>
Subject: Re: [CommunityToolkit/Maui] Add New Enum Description Converter (PR #3137)
[https://avatars.githubusercontent.com/in/285228?s=20&v=4]dotnet-policy-service[bot] left a comment (CommunityToolkit/Maui#3137)<#3137 (comment)>
@BillyMartin1964<https://github.com/BillyMartin1964> the command you issued was incorrect. Please try again.
Examples are:
@dotnet-policy-service agree
and
@dotnet-policy-service agree company="your company"
—
Reply to this email directly, view it on GitHub<#3137 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AG7UTMTXKO5V27UABCO6TEL4P67TLAVCNFSM6AAAAACWMWHSWOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DAMRZGI3TINBZGA>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
There was a problem hiding this comment.
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:
DescriptionAttributeDisplayAttribute.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:
- Separate this into two separate converters:
EnumDescriptionConverter : BaseConverterOneWay<Enum, string?>EnumDisplayNameConverter : BaseConverterOneWay<Enum, string?>
- Create an
enumthat allows the developer to choose which value is returned
- This would be similar to our implementation for the
CompareConverterStringToListConverterand how it allows developers customization via its enumOperatorType
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.
| { | ||
| ArgumentNullException.ThrowIfNull(value); | ||
| var fieldInfo = value.GetType().GetField(value.ToString()); | ||
|
|
There was a problem hiding this comment.
Is this possible without reflection?
| public partial class EnumDescriptionConverter : BaseConverterOneWay<Enum, string> | ||
| { | ||
| /// <inheritdoc/> | ||
| public override string DefaultConvertReturnValue { get; set; } = string.Empty; |
There was a problem hiding this comment.
| 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> |
There was a problem hiding this comment.
| 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.
| /// 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) |
There was a problem hiding this comment.
| 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 |
There was a problem hiding this comment.
| 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.
|
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 problem. Here's the discussion link: 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. |
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
PR Checklist
approved(bug) orChampioned(feature/proposal)mainat time of PRAdditional information
Example use case: