问题
I am reading this http://msdn.microsoft.com/en-us/magazine/jj651572.aspx to learn mvvm light framework. I download the source code Friend.cs.
My question is why some set method of different property are implemented differently.
For example, the setter for First name is, why I need 'ref' keyword for _firstName.
Set(FirstNamePropertyName, ref _firstName, value);
And the setter for DateOfBirthString is "
RaisePropertyChanged(() => DateOfBirth);
When will the linq expression will be evaluated?
namespace MyFriends.Model
{
[SimpleSerialize]
public class Friend : ObservableObject
{
/// <summary>
/// The <see cref="FirstName" /> property's name.
/// </summary>
public const string FirstNamePropertyName = "FirstName";
private string _firstName;
/// <summary>
/// Sets and gets the FirstName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "first_name")]
public string FirstName
{
get
{
return _firstName;
}
set
{
Set(FirstNamePropertyName, ref _firstName, value);
}
}
/// <summary>
/// The <see cref="LastName" /> property's name.
/// </summary>
public const string LastNamePropertyName = "LastName";
private string _lastName;
/// <summary>
/// Sets and gets the LastName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "last_name")]
public string LastName
{
get
{
return _lastName;
}
set
{
Set(LastNamePropertyName, ref _lastName, value);
}
}
/// <summary>
/// The <see cref="DateOfBirth" /> property's name.
/// </summary>
public const string DateOfBirthPropertyName = "DateOfBirth";
private string _dateOfBirthString;
/// <summary>
/// Sets and gets the DateOfBirth property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "birthday")]
public string DateOfBirthString
{
get
{
return _dateOfBirthString;
}
set
{
_dateOfBirthString = value;
RaisePropertyChanged(() => DateOfBirth);
}
}
public DateTime DateOfBirth
{
get
{
if (string.IsNullOrEmpty(_dateOfBirthString))
{
return DateTime.MinValue;
}
return DateTime.ParseExact(DateOfBirthString, "d", CultureInfo.InvariantCulture);
}
set
{
_dateOfBirthString = value.ToString("d", CultureInfo.InvariantCulture);
}
}
private string _imageUrl;
[SimpleSerialize(FieldName = "picture")]
public string ImageUrl
{
get
{
return _imageUrl;
}
set
{
_imageUrl = value;
RaisePropertyChanged(() => ImageUri);
}
}
public Uri ImageUri
{
get
{
return new Uri(_imageUrl);
}
}
}
}
回答1:
The difference between those two methods is that the Set
method replaces the old value of the _firstName
field and then raises the PropertyChanged
event, while the RaisePropertyChanged
only raises the PropertyChanged
event.
You'll want to use the Set
method in most cases, since it helps to shorten property declarations by wrapping all that typically needs to be done within a property's setter in just one method:
- It updates the value of the passed field and overwrites it with the content of
value
, and then - raises the
PropertyChanged
event to notify Views about this update.
The reason the field needs to be passed by reference (thus using ref _firstName
) is that not the field's content is needed within the Set
method, but the field itself is actually updated.
The RaisePropertyChanged
method is useful when an update of one property does also affect additional properties. In this case, these properties' contents need to be updated manually, then the RaisePropertyChanged
method can be called to inform Views about which properties have actually changed.
回答2:
One instance I found that Set(ref _prop, value) doesn't work is when you need to resend an update or need to do a custom comparison. Set(ref _prop, value) will do a compare on the _prop and value for you but it may not be what you want. For some properties i may want to add some more conditions beyond just a comparison in which case I'll set the _prop = value manually and then raise the change right after;
But in most cases I use the Set(ref _prop, value)
回答3:
Here is an actual usage, where the IsRunning
is the primary operation, but it also raises a change notification on the property IsComplete
which is based on IsRunning
. This way both properties send a notify without undo extra coding.
private bool _IsRunning;
public bool IsRunning
{
get => _IsRunning;
set
{
SetProperty(ref _IsRunning, value);
RaisePropertyChanged("IsComplete");
}
}
public bool IsComplete => !IsRunning;
来源:https://stackoverflow.com/questions/26293193/difference-between-set-and-raisepropertychanged