Lindsay
Lindsay

Reputation: 595

Is there a better way to show enums in a control, eg combobox

My goal is to present to the user the list of available enum's in a user friendly string format rather than the code value, and display said property when required. Given that the DataAnnotations namespace doesn't exist in 8.1 universal apps, I can't simply apply [Display(Name="Nice display string")].

I have instead, used IValueConverter to run a switch statement on the incoming enum and return the string I want, and same in reverse, and will throw an exception if unable to convert. In the viewmodel, I am returning a List<Enum> as the bindable data source (for the combobox), for which the selected item is bound to the relative property in the viewmodel.

When testing, this works - the strings display in user friendly format, the property is changing and correctly setting the enum value. However, the Visual Studio designer (randomly) throws a xaml parse exception (Which I'm pretty sure is thrown due to the binding markup on the combobox.itemtemplate), which is never ideal.

So, my question - Is there a better way achieve my goal without throwing exceptions? Is the xaml error something to be concerned about even though the app compiles and runs?

My converter

public class FactToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        Fact input = (Fact)value;
        switch (input)
        {
            case Fact.Wrong:
                return "Your Fact is Incorect";
            case Fact.Right:
                return "Your Fact is Correct";
            default:
                throw new ArgumentOutOfRangeException("value", "Fact to string conversion failed as selected enum value has no corresponding string output set up.");
        }
    }
}

My Bindable Itemssource

public List<Fact> FactList
{
    get
    {
        return new List<Fact>
        {
            Fact.Wrong,
            Fact.Right,
        };
    }
}

and my xaml

<ComboBox Header="Sample Fact:" Margin="0,10" ItemsSource="{Binding FactList}"
          SelectedItem="{Binding CurrentFact, Mode=TwoWay}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Grid DataContext="{Binding}">
                <TextBlock Text="{Binding Converter={StaticResource FactConv}}"/>
            </Grid>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Upvotes: 0

Views: 414

Answers (3)

Lindsay
Lindsay

Reputation: 595

Display Attribute Implementation

[System.AttributeUsage(System.AttributeTargets.All)]
public class Display : System.Attribute
{
    private string _name;
    public Display(string name)
    { _name = name; }
    public string GetName()
    { return _name; }
}

Converter

public class EnumWithDisplayConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        try
        {
            string output = value.GetType()
                .GetTypeInfo()
                .GetDeclaredField(((Enum)value).ToString())
                .GetCustomAttribute<Display>()
                .GetName();
            return output;
        }
        catch (NullReferenceException)
        {
            return ((Enum)value).ToString();
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Upvotes: 2

yasen
yasen

Reputation: 3580

The VS designer does throw some exceptions randomly for no reason, so it's not really all that important. Now, if the exception is thrown at runtime - that's a serious problem and you need to resolve it!

On a side note: you don't need that DataContext={Binding} on the Grid in the DataTemplate.

Upvotes: 0

David Arno
David Arno

Reputation: 43254

Just because the DisplayAnnotations namespace is missing, doesn't mean you can't use Display. Simply create your own attribute class. Please see this answer to another question for how to do that.

Upvotes: 1

Related Questions