6

Possible Duplicate:
Setting the default value of a DateTime Property to DateTime.Now inside the System.ComponentModel Default Value Attrbute

Im creating a control like a calendar, and I want user to set de year they want to view. But If they don't, the property of SelectedYear must be the actual year.

I try setting this Default Value like this:

[DefaultValue(DateTime.Today.Year)]
public int SelectedYear{
    get{
        return _selYear;
    }
    set{
        _selYear = value;
        UpdateCalendar();
    }
}

And I got the following error

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
Community
  • 1
  • 1
jcvegan
  • 3,111
  • 9
  • 43
  • 66
  • That's not what that attribute is for. Setting default property values in the default ctor of the class is one common option. – asawyer Oct 24 '12 at 17:02
  • This is the designer default value, means if the control has the given year value, the value will not be bold in the properties window. It doesn't effect the property value. – Amiram Korach Oct 24 '12 at 17:03
  • If you are building a control then I believe setting the default value in constructor will be a good place. – jags Oct 24 '12 at 17:03
  • You should use the `AmbientValueAttribute` class, to define a value that when set to the property, really means the current date... take a look at my answer. Also, this gives clues to the designer on how the control works. – Miguel Angelo Oct 24 '12 at 17:23

7 Answers7

7

The Year property of DateTime is a calculated value but you're trying to embed it into an attribute which is an immutable value stored in the binary. These two concepts aren't compatible.

What you want to do here is have a marker to note that the value isn't set yet and to return the current Year in that case. This is a good place to use a nullable

int? _selYear;
public int SelectedYear {
  get { return _selYear ?? DateTime.Today.Year; }
  set { 
    _selYear = value;
    UpdateCalendar();
  }
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
3

Use AmbientValueAttribute to indicate that when you set the property to the default value, it actually means to get the current date.

int _selYear = 0;

[AmbientValue(0)]
[DefaultValue(0)]
public int SelectedYear{
    get{
        if (_selYear == 0)
            return DateTime.Today.Year;
        return _selYear;
    }
    set{
        _selYear = value;
        UpdateCalendar();
    }
}

If you want to use the 0 value, then you can make it nullable, but never return null, only allow setting null:

int _selYear = null;

[AmbientValue(null)]
[DefaultValue(null)]
public int? SelectedYear{
    get{
        return _selYear ?? DateTime.Today.Year;
    }
    set{
        _selYear = value;
        UpdateCalendar();
    }
}

Now, it is the null value that represents the current year.

The AmbientValueAttribute means: if you set this property to that value, when you get the property, another value will be returned from the environment, and that the return value in that case may vary, just like the current date.

Miguel Angelo
  • 23,796
  • 16
  • 59
  • 82
1

You should initialize a value of a property explicitly. The DefaultValue attribute does not initialize property by the value it just provide metadata which value is default.

You can initialize it in ctor of a type or you can write a custom code which will reflect a type and initialize properties by the values from the type metadata.

Viacheslav Smityukh
  • 5,652
  • 4
  • 24
  • 42
0

Well, the error is pretty clear:

An attribute argument must be a constant expression...

So, if that did work, what would the default value actually be? Well, it would be the year in which you compiled the code. Probably not what you want.

If you really want to return the current year by default then simply initialize it to that in your constructor.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
0

Why not set the backing field instead like this in constructor -

_selYear = DateTime.Today.Year

It will then always be default value if user doesn't set it.

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
0

DateTime.Today.Year is not a constant value, since it changes every year. You could check whether the _selYear has been specified or not using this:

public int SelectedYear{
    get{
        if (_selYear.Equals(0)){
            return  DateTime.Today.Year;
        }
        else{
            return _selYear;
        }
    }
    set{
        _selYear = value;
        UpdateCalendar();
    }
}

This is considering you initiated _selYear to 0.

Francis P
  • 13,377
  • 3
  • 27
  • 51
0

This is because the DefaultValue only accepts constant values. You can do this via another approach some thing like below

public int SelectedYear{
    get{
        return _selYear == 0 ? DateTime.Now.Year : _selYear;
    }
    set{
        _selYear = value;
        UpdateCalendar();
    }
}

Hope this will help !!

Kundan Singh Chouhan
  • 13,952
  • 4
  • 27
  • 32