Reputation: 595
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
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
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
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