I have decorated the following enum with Display DataAnnotation attributes:
public enum RequiredOptions
{
[Display(Name="Optional",Description ="Optional")]
Optional,
[Display(Name="Not Used",Description ="Not Used")]
NotUsed,
[Display(Name="Required",Description ="Required")]
Required
}
I'd like to read out the Name value of the Display attribute for a given enum value in my code. How do I do this?
public static string DisplayRequiredOptionName(RequiredOptions opt)
{
// Return the value of Name from the display attribute from opt
}
Well, after doing some digging in the MVC source code (see src\System.Web.Mvc\Html\SelectExtensions.cs, see GetDisplayName()), here's what I got to work:
public static string GetEnumDisplayName<T>(T enumInstance)
{
return GetDisplayName(enumInstance.GetType().GetField(enumInstance.ToString()));
}
private static string GetDisplayName(FieldInfo field)
{
DisplayAttribute display = field.GetCustomAttribute<DisplayAttribute>(inherit: false);
if (display != null)
{
string name = display.GetName();
if (!String.IsNullOrEmpty(name))
{
return name;
}
}
return field.Name;
}
Related
I have this class:
public class TranslationItem : CmsDto
{
[Required(LocalizationManager.Guid, ErrorMessage = LocalizationManager.Validation_Required)]
public string FirstField
{
get { return GetValue(() => FirstField); }
set { SetPropertyValue(value); }
}
[Required(LocalizationManager.Guid, ErrorMessage = LocalizationManager.Validation_Required)]
public string SecondField
{
get { return GetValue(() => SecondField); }
set { SetPropertyValue(value); }
}
}
It used to create two-way binding for localizations for my entities.
Properties First and Second Field have required attribute and must have String Length attribute.
public ObservableCollection<TranslationItem> PairValues
{
get { return _pairValues; }
private set { SetProperty(ref _pairValues, value); }
}
Property in my VM.
My question is: Can I create custom String Length Attribute with dynamic max length value?
For example, have 2 PairValues Collection's in my VM, but first has 255 and 500 (first and second field) and second has 255 and 255?
Anyway, I need to have ability to choose any string length in xaml or VM for every use in my project.
I'm looking at some code and found this kind of pattern:
private string text { get; set; }
public string Text
{
get
{
return text;
}
set
{
text= value;
RaisePropertyChanged("Text");
}
}
I normally just back my public properties with private fields.
Is there any reason a property should be backed by a private property like this? My instinct is to say that it shouldn't, and this should be backed by a field instead, is that right? Any technical reasons I can use to back this up?
Typical case is when you have a raw data (data as it is without any transformation) and the same data, but friendly represented:
private String m_RawText;
// Text as it's obtained from, say, database
private string rawText {
get {
if (null == m_RawText)
m_RawText = ReadValueFromDataBase();
return m_RawText;
}
set {
if (m_RawText != value) {
UpdateValueInDataBase(value);
m_RawText = value;
}
}
}
// Friendly encoded text, for say UI
public string Text {
get {
return EncondeText(rawTex);
}
set {
rawText = DecodeText(value);
RaisePropertyChanged("Text");
}
}
// Here we want rawText
public void PerformSomething() {
String text = rawText; // we want raw text...
...
}
// And here we prefer Text
public override String ToString() {
return String.Fromat("Text = {0} ", Text, ...)
}
I have created a class that contains two variables: Type & Value. If the first property (Type) is filled, the second property (Value) can only contain a value that matches the type which is selected on the Type property.
public class Requirement
{
public RequirementType Type { get; set; }
public object Value { get; set; }
public enum RequirementType
{
OS, NetFramework, Connection
}
public enum OSType
{
// Used for RequirementType.OS
Win, Unix, MacOSX
}
public enum NetFrameworkType
{
// Used for RequirementType.NetFramework
Two, Three, Four, FourHalf
}
public enum ConnectionType
{
// Used for RequirementType.Connection
Internet, Connected, None
}
}
I'm using this class in the XAML:
<util:Requirement Type="OS" Value="Win" />
So for example, if the enum value OS has been chosen. The only valid values should be from the enum OSType. I started looking in the .Net source how they solved this with the System.Windows.Trigger & System.Windows.Setter but no success yet.. It seems to be something with the DependsOn attribute and XamlSetTypeConverterAttribute. Does someone know the solution to this problem?
You can use a backing field for value and check each type as it's being set.
public class Requirement
{
public RequirementType Type { get; set; }
private object _value;
public object Value
{
get { return _value; }
set
{
if (Type == RequirementType.OS &&
value.GetType() == typeof(OSType))
{
_value = value;
}
else
{
throw new Exception("Value type is incorrect for Type provided");
}
}
}
}
This test will throw the exception:
var req = new Requirement();
req.Type = RequirementType.OS;
req.Value = RequirementType.Connection;
While this second test will properly set the value:
var req = new Requirement();
req.Type = RequirementType.OS;
req.Value = OSType.Win;
You can use normal properties (type propful and hit Tab):
private RequirementType _type;
public RequirementType Type
{
get { return _type; }
set
{
_type = value;
// do whatever logic you want here
}
}
I am using vs 2012. I have a simple string property
string _someString;
public string MyString
{
get
{
return _someString;
}
}
I want this property to hold only certain values. So that when the client uses this property only those certain values can be used.
It sounds like what you really want is an enum:
public enum MyValues //TODO rename all the things
{
SomeValue,
SomeOtherValue,
FinalValue,
}
Then your property can be:
private MyValues value;
public MyValues MyValue
{
get { return value; }
}
If you need to get a string representation of that value just call ToString on the enum value:
string stringValue = value.ToString();
Use an enum as in :
enum MyEnum
{
AllowableValue#1,
AllowableValue#2,
...
}
public MyEnum myEnum { get; set; }
Then populate some UI element with only the values of the enum.
I suppose you want to have some validation on the setter then:
public string MyString
{
get
{
return _someString;
}
set
{
if (value == "a" || value == "b" /* ... */)
_someString = value;
else
throw new InvalidArgumentException("Invalid value!");
}
}
Make sure to set it via the property, not the actual member variable.
i need an enum or something similiar to do something like this:
public enum MyStringEnum {
[StringValue("Foo A")] Foo = "A",
[StringValue("Foo B")] Foo = "B" }
is this possible? my example, i return back a dataset with a value represented as either A,B,C,D,E .. i need a solution to return this as a string representation?
i guess the obvious would be to create an extension method or something which just had a switch statement in and return a string .. any other cleaner solutions?
regards,
dave
Here is something we use for our MVC applications to retrieve a display name for our enums. It uses a custom attribute and an extension method to retrieve the enum display name.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDisplayNameAttribute : Attribute
{
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public static string GetDisplayName(this Enum enumType)
{
var displayNameAttribute = enumType.GetType()
.GetField(enumType.ToString())
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.FirstOrDefault() as EnumDisplayNameAttribute;
return displayNameAttribute != null ? displayNameAttribute.DisplayName : Enum.GetName(enumType.GetType(), enumType);
}
Usage on the enum:
public enum Foo
{
[EnumDisplayName("Foo Bar")]
Bar = 0
}
Getting back the display name:
var f = Foo.Bar;
var name = f.GetDisplayName();
Would it be an option not to use enum and use structs instead?
struct FooEnum
{
private int value;
private string name;
private FooEnum(int value, string name)
{
this.name = name;
this.value = value;
}
public static readonly FooEnum A = new FooEnum(0, "Foo A");
public static readonly FooEnum B = new FooEnum(1, "Foo B");
public static readonly FooEnum C = new FooEnum(2, "Foo C");
public static readonly FooEnum D = new FooEnum(3, "Foo D");
public override string ToString()
{
return this.name;
}
//TODO explicit conversion to int etc.
}
You could then use FooEnum like an enum with an own ToString() overload:
FooEnum foo = FooEnum.A;
string s = foo.ToString(); //"Foo A"
If you want to do something like this:
MyStringEnum value = MyStringEnum.A;
string description = value.GetDescription();
// description == "Foo A"
Setup your enum like this:
public enum MyStringEnum
{
[Description("Foo A")]
A,
[Description("Foo B")]
B
}
And use a utility/extension method that reads the attribute:
public static string GetDescription(this MyStringEnum enumerationValue)
{
Type type = enumerationValue.GetType();
string name = enumerationValue.ToString();
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] member = type.GetMember(name);
if (member != null && member.Length > 0)
{
object[] attributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
return name;
}
I've seen this done where I would put
MyStringEnum.Foo.ToString();
In this case it would give "A"
The cleanest solution for this problem is to create a custom attribute that will store the string value you want for the enum constant. I've used that strategy in the past and it worked out fairly well. Here's a blog post detailing the work involved:
Enum With String Values In C# - Stefan Sedich's Blog
Of course this is only necessary if you need some kind of meaningful text. If the name of the enum constant works for you...then you can simply call ToString().