Skip to content

MVVM Attributes

Jan M edited this page Mar 13, 2021 · 3 revisions

DependsOn

This attributes indicates that a certain property should raise a PropertyChanged event when some other property did raise this event. Common scenarios are read-only calculated values like the age of a person. In the following example, a PropertyChanged event for Age will always occur when DateOfBirth has changed.

public DateTime DateOfBirth
{
    get => GetValue<DateTime>();
    set => SetValue(value);
}

[DependsOn(nameof(DateOfBirth))]
public int Age =>
    DateTime.Now.Year - DateOfBirth.Year;

SupressNotifyPropertyChanged

If you want to use the convinient methods GetValue<T> and SetValue<T> for properties, but for some reason there should be no PropertyChanged event, this attribute will come to the rescue. It is possible to tag certain properties or whole classes, you can even supress the event for a whole class but allow it for some properties. The following examples will demonstrate each scenario.

// Supress PropertyChanged for a single property
public class SomeModel
{
    public string Name
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    [SupressNotifyPropertyChanged]
    public string Supressed
    {
        get => GetValue<string>();
        set => SetValue(value);
    }
}

// Supress PropertyChanged for whole class
[SupressNotifyPropertyChanged]
public class SupressedClass
{
    // no property will raise a PropertyChanged event
}

// Supress PropertyChanged for whole class but exclude one special property
[SupressNotifyPropertyChanged]
public class SupressedClass
{
    // this won't raise PropertyChanged
    public int SupressedId
    {
        get => GetValue<int>();
        set => SetValue(value);
    }

    // this won't raise PropertyChanged
    public string SupressedName
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    // this will raise PropertyChanged
    [SupressNotifyPropertyChanged(Supress=false)]
    public string SpecialProperty
    {
        get => GetValue<string>();
        set => SetValue(value);
    }
}

IsRelevantForCommand

The attribute is used to tag properties that should update a certain ICommand's CanExecute state. It is possible to either specify a command by its name or use the attribute without any parameter to force updating all ICommands in the class.

In the following example, changing Username would re-evaluate CanExecute of the LoginCommand whereas changing Password would check CanExecute on both LoginCommand and ResetPasswordCommand:

public class LoginViewModel
{
    [IsRelevantForCommand(nameof(LoginCommand))]
    public string Username
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    [IsRelevantForCommand]
    public string Password
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    public ICommand LoginCommand { get; }
    public ICommand ResetPasswordCommand { get; }
}

DontAffectIsDirty

If you are using our ModelBase, you may have already noticed the IsDirty property it provides. The property indicates whether one or multiple tracked properties have changed since the last time CommitChanges() has been called.
If you want to exclude properties from setting your model to dirty, you can just tag them with this attribute:

public class EpicModel
{
    // changing Name will set IsDirty = true
    public string Name
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    // this should not set IsDirty = true
    [DontAffectIsDirty]
    public bool SomeInternalFlag
    {
        get => GetValue<bool>();
        set => SetValue(value);
    }
}
Clone this wiki locally