Search code examples
c#xamlenumscomboboxwinui-3

WinUI 3 - Bind a combobox to a enum and display the Display property


I don't figure out a solution for a clean and resuable code for bind a enum to a combobox in WinUi 3.

I have a general class that holds all the enum of my projects and in that I have this code:

    public class Enums
    {
        public enum ViewMode
        {
            [Display(Name = "Come nel dispositivo")]
            AsDevice,
            [Display(Name = "Chiaro")]
            Light,
            [Display(Name = "Scuro")]
            Dark
        }
    }

In the ViewModel file I have this code:

private IList<Enums.ViewMode> _viewsMode = Enum.GetValues(typeof(Enums.ViewMode)).Cast<Enums.ViewMode>().ToList();

public IList<Enums.ViewMode> ViewsMode => _viewsMode;
public Enums.ViewMode ViewMode
{
    get { return _model.ViewMode; }
    set
    {
        if (_model.ViewMode != value)
        {
           _model.ViewMode = value;
           RaisePropertyChanged();
           UpdateCommand.RaiseCanExecuteChanged();
         }
     }
}

Finally in the xaml file I have this code:

<ComboBox Width="160" ItemsSource="{x:Bind ViewModel.ViewsMode}" SelectedItem="{x:Bind ViewModel.ViewMode,Mode=TwoWay}"/>

And so far so good, it works perfectly. but it display "AsDevice" or "Light" or "Dark" while I want to display the DisplayName property as "Come nel dispositivo" or "Chiaro" or "Scuro", How can I do that? Thanks to everyone


Solution

  • You can do this with a ValueConverter:

    public class EnumToDisplayNameConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return value is Enum enumValue &&
                enumValue.GetType()
                    .GetMember(enumValue.ToString())
                    .FirstOrDefault()
                        ?.GetCustomAttribute<DisplayAttribute>()
                        ?.GetName() is string displayName
                            ? displayName
                            : $"Unknow value: {value}";
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
    

    and use it like this:

    <Page
        x:Class="EnumDisplayNameExample.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="using:EnumDisplayNameExample"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        mc:Ignorable="d">
        <Page.Resources>
            <local:ViewModel x:Name="ViewModel" />
            <local:EnumToDisplayNameConverter x:Key="EnumToDisplayNameConverter" />
        </Page.Resources>
    
        <StackPanel>
            <ComboBox
                Width="160"
                ItemsSource="{x:Bind ViewModel.ViewsMode}"
                SelectedItem="{x:Bind ViewModel.ViewMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Converter={StaticResource EnumToDisplayNameConverter}}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
            <TextBlock Text="{x:Bind ViewModel.ViewMode, Mode=OneWay, Converter={StaticResource EnumToDisplayNameConverter}}" />
        </StackPanel>
    
    </Page>