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.
Related
I may not have a good grasp of the ?? operator yet and ran into a design flaw I couldn't explain.
Compare the following two properties, the only difference being how there are initialized: the first explicitly initialized, while the second with the ?? operator (or am I doing it wrong here?).
If I run data init with both properties, the collection based on the first property comes up populated as expected, while the second one with the ?? operator never gets populated and comes up with 0 elements in the collection.
Surely something is wrong here in my assumption; what is the flaw here?
P.S. Please ignore the Set method which is to implement INotifyPropertyChanged in the base class and has no bearing on this issue (which is confined to the type of initialization).
// property version 1
private ObservableCollection<UserName> _userNameColl = new ObservableCollection<UserName>();
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl; }
set { Set(ref _userNameColl, value); }
}
// property version 2
private ObservableCollection<UserName> _userNameColl;
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl ?? new ObservableCollection<UserName>(); }
set { Set(ref _userNameColl, value); }
}
// a simple class for creating object collection
public class UserName
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
// a simple test populating the collection
for (int i = 0; i < 4; i++)
{
// silly data init just for test
UserNameColl.Add(new UserName()
{
Name = $"UserName No {i}",
Age = 20 + i,
Email = $"email{i}#local.lan"
});
}
The second one never initializes your field but always returns a new collection. Try this one instead:
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl ?? (_userNameColl = new ObservableCollection<UserName>()); }
set { Set(ref _userNameColl, value); }
}
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;
}
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.