The XAML Data Link does not update the user interface when the property changes

advertisements

I'm having trouble getting a simple data bound label to update when an integer field is changed. I've implemented INotifyPropertChanged and this event gets fired when I chang my variables value. The UI does not update and the label does not change. I haven't done much data binding in the past so I'm probably missing something but I haven't been able to find it yet.

Here is what I have for my XAML:

         <Window x:Class="TestBinding.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-
                compatibility/2006"
                xmlns:local="clr-namespace:TestBinding"
                mc:Ignorable="d"
                Title="MainWindow" Height="350" Width="525">
            <StackPanel>
                <Button Command="{Binding TestCommand, Mode=OneWay}" >
                    <Button.DataContext>
                        <local:TestVM/>
                    </Button.DataContext> Add 1</Button>
                <Label Content="{Binding Count,
                 Mode=OneWay,UpdateSourceTrigger=PropertyChanged}">
                    <Label.DataContext>
                        <local:TestVM/>
                    </Label.DataContext>
                </Label>
            </StackPanel>
        </Window>

Here is my View Model C#:

class TestVM : INotifyPropertyChanged
    {
        private int _count;
        private RelayCommand _testCommand;

        public TestVM ()
        {
            Count=0;

        }

        public int Count
        {
            get { return _count; }
            set { _count = value; OnPropertyChanged(); }
        }

        public void Test()
        {
            Count++;
        }

        public ICommand TestCommand
        {
            get
            {
                if (_testCommand == null)
                {
                    _testCommand = new RelayCommand(param => this.Test(), param => true);
                }

                return _testCommand;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                Console.WriteLine(propertyName);
                var e = new PropertyChangedEventArgs(propertyName);
                this.PropertyChanged(this, e);
            }
        }
    }

Here is my ICommand C# (In case you need it to replicate what I have):

public class RelayCommand : ICommand
    {
        #region Fields
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;
        #endregion // Fields 

        #region Constructors
        public RelayCommand(Action<object> execute) : this(execute, null) { }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null) throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
        #endregion // Constructors 

        #region ICommand Members [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
        #endregion
        // ICommand Members
    }

Any and all help is greatly appreciated.

EDIT: I updated my xaml to what toadflakz suggested and it worked.

<Window x:Class="TestBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:TestVM/>
    </Window.DataContext>
    <StackPanel>
    <Button Command="{Binding TestCommand, Mode=OneWay}" >Add 1</Button>
    <Label Content="{Binding Count, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>


Your issue is with the way you are binding the DataContext to the individual controls. Your ViewModel is not automatically a Singleton (single instance only object) so each time you specify it, you're actually creating a separate instance.

If you set the DataContext at the Window level, your code should work as expected.