Set()和RaisePropertyChanged()之间的区别

时间:2014-10-10 06:26:23

标签: mvvm mvvm-light

我正在阅读这个http://msdn.microsoft.com/en-us/magazine/jj651572.aspx来学习mvvm轻型框架。 我下载了源代码Friend.cs。

我的问题是为什么不同属性的某些set方法的实现方式不同。

例如,名字的setter是,为什么我需要_firstName的'ref'关键字。

 Set(FirstNamePropertyName, ref _firstName, value);

DateOfBirthString的setter是“

RaisePropertyChanged(() => DateOfBirth);

何时会评估linq表达式?

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);
            }
        }
    }
}

3 个答案:

答案 0 :(得分:2)

这两种方法之间的区别在于Set方法替换_firstName字段的旧值,然后引发PropertyChanged事件,而RaisePropertyChanged只引发PropertyChanged Set事件。

在大多数情况下,您希望使用value方法,因为它通过在一个方法中包含通常需要在属性的setter中完成的所有操作来缩短属性声明:

  1. 它会更新传递的字段的值,并使用PropertyChanged的内容覆盖它,然后
  2. 引发ref _firstName事件以通知有关此更新的视图。
  3. 该字段需要通过引用传递(因此使用Set)的原因是,RaisePropertyChanged方法中不需要字段的内容,但字段本身实际上已更新

    当一个属性的更新也影响其他属性时,RaisePropertyChanged方法很有用。在这种情况下,这些属性&#39;内容需要手动更新,然后可以调用{{1}}方法来通知Views实际更改了哪些属性。

答案 1 :(得分:0)

我发现一个实例Set(ref _prop,value) 当您需要重新发送更新或需要进行自定义比较时,它不起作用。设置(ref _prop,value)  会对你的_prop和值进行比较,但它可能不是你想要的。对于某些属性,我可能想要添加更多条件而不仅仅是比较,在这种情况下,我将手动设置_prop =值,然后立即提高更改;

但在大多数情况下,我使用Set(ref _prop,value)

答案 2 :(得分:0)

这是一种实际用法,其中IsRunning是主要操作,但它还会基于IsComplete在属性IsRunning上发出更改通知。这样,两个属性都会发送通知,而无需撤消额外的编码。

private bool _IsRunning;

public bool IsRunning
{
    get => _IsRunning;
    set
    {
        SetProperty(ref _IsRunning, value);
        RaisePropertyChanged("IsComplete");
    }
}

public bool IsComplete => !IsRunning;