简体   繁体   中英

DependencyObject is not updating the View

I have a ViewModel that is a DependencyObject for which the DependencyProperty s are not updating the View with the new values.

A sample property (the get/set wrapper is called as expected)

public static readonly DependencyProperty WeaponNameProperty = DependencyProperty.Register(
        "WeaponName",
        typeof(string),
        typeof(WeaponSystemVM),
        new PropertyMetadata(null, new PropertyChangedCallback(OnWeaponNameChanged)));
    public string WeaponName
    {
        get { return (string)GetValue(WeaponNameProperty); }
        set { SetValue(WeaponNameProperty, value); }
    }

The Callback (called when WeaponName is changed)

private static void OnWeaponNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    WeaponSystemVM vm = d as WeaponSystemVM;
    if (vm != null)
    { vm.CommandAddWeaponSystem.RaiseCanExecuteChanged(); }
}

The CanExecute Delegate (gets run as expected and updates the relevant Button )

private bool CanAddSystem()
{
    if (string.IsNullOrWhiteSpace(WeaponName)) return false;
    if (string.IsNullOrWhiteSpace(WeaponLock)) return false;
    if (string.IsNullOrWhiteSpace(WeaponDamage)) return false;
    if (string.IsNullOrWhiteSpace(WeaponAttack)) return false;
    return true;
}

The input TextBox

<TextBox x:Name="NameInput" Text="{Binding WeaponName, Mode=TwoWay}" Margin="12,4" RelativePanel.Below="NameAdorner" RelativePanel.AlignLeftWithPanel="True"
                     RelativePanel.AlignRightWithPanel="True"/>

The output TextBlock (is NOT updated with the new value and the DataContext is the same as the input TextBox )

<TextBlock Text="{Binding WeaponName}"/>

Frustratingly, it seems to be just this implementation that isn't working.
In an attempt to reproduce the issue, I created a seperate project without all the extra info associated with my app, and the View is being updated exactly as expected.

What I don't understand is what is not being done correctly in this implementation. The ViewModel is updating exactly as expected. The Bindings are valid according to the LiveVisualTree .
Can anyone point me to the issue?

You shouldn't use DependencyProperty s in your ViewModel: it is a markup class, used for binding on the View side. Overkill and out of scope for it being used that way.
You should implement INotifyPropertyChanged , and fire the INotifyPropertyChanged.PropertyChanged event in every single property you want to notify the UI about.
Something like:

your ViewModel inherits from

public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void SetAndRaiseIfChanged<T>(
        ref T backingField,
        T newValue,
        [CallerMemberName] string propertyName = null)
    {
        if (!object.Equals(backingField, newValue))
            return;

        backingField = newValue;
        this.RaisePropertyChanged(propertyName);
    }
}

and in your ViewModel you define your property like

private string _weaponName;
public string WeaponName
{
    get { return this._weaponName; }
    set { SetAndRaiseIfChanged(ref this._weaponName, value); }
}

a more concise CanAddSystem

private bool CanAddSystem()
{
    return 
        !string.IsNullOrWhiteSpace(WeaponName)
        && !string.IsNullOrWhiteSpace(WeaponLock)
        && !string.IsNullOrWhiteSpace(WeaponDamage)
        && !string.IsNullOrWhiteSpace(WeaponAttack);
}

build your ViewModel's command with something that implements ICommand interface (something like a RelayCommand)

the View piece would be

<TextBlock Text="{Binding WeaponName}"/>

and you're done: when you bind an ICommand to the UI, the system automatically updates the CanExecute reading it from the ViewModel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM