Skip to main content

BindableBase

  • 8 minutes to read

The BindableBase class implements the INotifyPropertyChanged interface and provides the API to declare bindable property with minimum coding.

Bindable Properties

To declare bindable properties, do the following:

  • inherit your ViewModel from the BindableBase class;
  • use the GetValue and SetValue methods in property getters and setters.
using DevExpress.Mvvm;

public class ViewModel : BindableBase {
    public string FirstName {
        get { return GetValue<string>(nameof(FirstName)); } 
        set { SetValue(value, nameof(FirstName)); }
    }
}

The BindableBase class exposes the GetValue and SetValue overloads that use the CallerMemberNameAttribute. You do not have to pass property name to these methods’ parameter. This simplifies the bindable property declaration:

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
    public string FirstName {
        get { return GetValue<string>(); } 
        set { SetValue(value); }
    }
}

Note

The CallerMemberNameAttribute is available in .NET Framework 4.5 and above.

The BindableBase in .NET Framework 4.0 section describes how to use the BindableBase View Model in .NET 4.0.

Property values are stored in an internal dictionary:

  • the GetValue method uses this dictionary to get a property value;
  • the SetValue method uses the property name as a key to store a property value in the dictionary.

The SetValue method returns True or False values that indicate whether a property has been changed. If you set the same value to the property, the SetValue method returns False and change notifications are not sent.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
    public string FirstName {
        get { return GetValue<string>(); }
        set {
            if (SetValue(value))
                NotifyFullNameChanged();
            else MessageBox.Show("Could not change value!");
        }
    }
}

Note

The simplified property declaration uses a dictionary to store property values. As a result, application performance can decrease when properties are frequently accessed or updated. To avoid this, you can use properties with backing fields.

Run Custom Code When Property Value Changed

The SetValue method has overloads that take a callback method as a parameter. This callback is invoked after a property value has been changed.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
        public string FirstName {
            get { return GetValue<string>(); }
            set { SetValue(value, changedCallback: OnFirstNameChanged); }
        }
        void OnFirstNameChanged() {
            //...
        }
    }

Manually Raise INotifyPropertyChanged.PropertyChanged

If you need to raise the INotifyPropertyChanged.PropertyChanged event for a specific property, use the RaisePropertyChanged/RaisePropertiesChanged method.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
    public string FirstName {
        get { return GetValue<string>(); }
        set { SetValue(value, changedCallback: NotifyFullNameChanged); }
    }

    public string LastName {
        get { return GetValue<string>(); }
        set { SetValue(value, changedCallback: NotifyFullNameChanged); }
    }

    public string FullName { get { return FirstName + " " + LastName; } }

    void NotifyFullNameChanged() {
        RaisePropertyChanged(nameof(FullName));
    }
}

Using Properties With Backing Fields

An application’s performance can decrease when a property is frequently accessed or updated because property values are stored in the Dictionary. To improve the application’s performance, store property values in backing fields.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
    string _FirstName;
    public string FirstName {
        get { return _FirstName; }
        set { SetValue(ref _FirstName, value, changedCallback: NotifyFullNameChanged); }
    }
}

Serialize Bindable Properties

The BindableBase class is marked with the DataContract attribute. As a result, the JSON serializer looks only for members marked with the DataMember attribute:

using DevExpress.Mvvm;
using System.Runtime.Serialization;
// ...
public class ViewModel : BindableBase {
    [DataMember]
    public string FirstName {
        get { return GetValue<string>(); } 
        set { SetValue(value); }
    }
}

BindableBase in .NET Framework 4.0

Bindable Properties

Use the GetProperty and SetProperty methods to implement bindable properties.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
        public string FirstName {
            get { return GetProperty(() => FirstName); }
            set { SetProperty(() => FirstName, value); }
        }
    }

The first parameter of the GetProperty and SetProperty methods is a lambda expression that returns the property used to identify the target property name. The property names are internally obtained with the static BindableBase.GetPropertyName<T> method.

Run Custom Code When Property Value Changed

The SetProperty method returns True or False values that indicate whether a property was changed. If you set the property to the same value, the SetProperty method returns False and changing notifications are not sent. The SetProperty method has overloads that take a callback method as a parameter. This callback is invoked after the field has been changed.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
        public string FirstName {
            get { return GetProperty(() => FirstName); }
            set { SetProperty(() => FirstName, value, OnFirstNameChanged); }
        }
        void OnFirstNameChanged() {
            //...
        }
    }

Manually Raise INotifyPropertyChanged.PropertyChanged

If you need to raise the INotifyPropertyChanged.PropertyChanged event for a specific property, use the RaisePropertyChanged/RaisePropertiesChanged method.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
        public string FullName {
            get { return string.Format("{0} {1}", FirstName, LastName); }
        }
        public string FirstName {
            get { return GetProperty(() => FirstName); }
            set { SetProperty(() => FirstName, value, OnFirstNameChanged); }
        }
        public string LastName {
            get { return GetProperty(() => LastName); }
            set {
                if(SetProperty(() => LastName, value))
                    RaisePropertyChanged(() => FullName);
            }
        }
        void OnFirstNameChanged() {
            RaisePropertyChanged(() => FullName);
        }
    }

Using Properties With Backing Fields

An application performance can decrease when a property is frequently updated (due to the calculation of property names from lambda expressions and storing property values in the Dictionary). To accommodate these scenarios, use storage variables for properties and calculate property names once from the static constructor using the BindableBase.GetPropertyName<T> method.

using DevExpress.Mvvm;

public class ViewModel : BindableBase {
        static string Property1Name;
        static ViewModel() {
            Property1Name = BindableBase.GetPropertyName(() => new ViewModel().Property1);
        }

        string property1;
        public string Property1 {
            get { return property1; }
            set { SetProperty(ref property1, value, Property1Name); }
        }
    }