简体   繁体   中英

WPF two way mode binding using INotifyPropertyChanged not working

So I am facing a tricky issue. This is my view model:

namespace Market.ViewModel
{
    public class BillingViewModel : ViewModelBase
    {
        #region Private Members

        private Customer _customer;
        private Product _products;
        private string _productId = "asd";
        RelayCommand _numClickedCommand;

        #endregion

        public Customer Customer
        {
            get { return _customer; }
            set
            {
                _customer = value;
                NotifyPropertyChanged("Customer");
            }
        }

        public Product Products
        {
            get { return _products; }
            set
            {
                _products = value;
                NotifyPropertyChanged("Products");
            }
        }

        public bool CanClick
        {
            get { return true; }
        }

        public string ProductId
        {
            get { return _productId; }
            set
            {
                _productId = value;
                NotifyPropertyChanged("ProductId");
            }
        }

        public ICommand NumClickedCommand
        {
            get
            {
                if (_numClickedCommand == null)
                {
                    _numClickedCommand = new RelayCommand(param => this.NumClicked(param.ToString()),
                        param => this.CanClick);
                }
                return _numClickedCommand;
            }
        }

        #region PrivateMethods

        private void NumClicked(string numClicked)
        {
            ProductId = ProductId+numClicked;
        }

        #endregion
    }
}

It inherits ViewModelBase which implements INotifyPropertyCanged.

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

And my view is:

<Window x:Class="Billing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:controls="clr-namespace:Billing"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <viewModel:BillingViewModel x:Key="ViewModel" />
    </Window.Resources>
    <Grid DataContext="{Binding Source={StaticResource ViewModel}}">
        <controls:NumPad HorizontalAlignment="Left" Margin="265,205,0,-192" VerticalAlignment="Top" Height="307" Width="242"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="247,29,0,0" TextWrapping="Wrap" Text="{Binding ProductId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>

NumClickedCommand is used in this xaml:

<UserControl x:Class="Billing.NumPad"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
         mc:Ignorable="d" Height="109" Width="248">

    <UserControl.Resources>
        <viewModel:BillingViewModel x:Key="ViewModel"/>
    </UserControl.Resources>
    <Grid Height="109" VerticalAlignment="Top" DataContext="{Binding Source={StaticResource ViewModel}}">
        <Button Content="1" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="1" Command="{Binding NumClickedCommand}"/>
        <Button Content="2" HorizontalAlignment="Left" Margin="90,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="2" Command="{Binding NumClickedCommand}"/>
        <Button Content="3" HorizontalAlignment="Left" Margin="170,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="3" Command="{Binding NumClickedCommand}"/>
        <Button Content="4" HorizontalAlignment="Left" Margin="10,27,0,0" VerticalAlignment="Top" Width="75" CommandParameter="4" Command="{Binding NumClickedCommand}"/>
        <Button Content="5" HorizontalAlignment="Left" Margin="90,27,0,0" VerticalAlignment="Top" Width="75" CommandParameter="5" Command="{Binding NumClickedCommand}"/>
        <Button Content="6" HorizontalAlignment="Left" Margin="170,27,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="1.034,2.171" CommandParameter="6" Command="{Binding NumClickedCommand}"/>
        <Button Content="7" HorizontalAlignment="Left" Margin="10,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="7" Command="{Binding NumClickedCommand}"/>
        <Button Content="8" HorizontalAlignment="Left" Margin="90,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="8" Command="{Binding NumClickedCommand}"/>
        <Button Content="9" HorizontalAlignment="Left" Margin="170,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="9" Command="{Binding NumClickedCommand}"/>
        <Button Content="0" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Width="75"  CommandParameter="0" Command="{Binding NumClickedCommand}"/>
        <Button Content="Submit" HorizontalAlignment="Left" Margin="90,81,0,0" VerticalAlignment="Top" Width="155" />

    </Grid>
</UserControl>

The problem is that updaditing ProductId in the viewmodel doesnt reflect in the view. The initial value of asd is updated at the launch of the application. The controls contain set of buttons that implements ICommand interface and it all calls the NumClicked() in viewmodel. While debugging if i click the button NumClicked() is called then ProductId is updated and NotifyPropertyChanged() is also called but UI does not update, it remains the same. But in case i directly update the UI ie i enter some value in the textbox the same flow happens, PropertyChanged() is called and after that get is also called to update the value in the viewmodel.

I have gone through many such questions already available but not able to get what exactly is stopping the update of the UI. Any help is appreciated and do ask if anything is missing. Thank You.

DataContext of Grid and TextBox are bound to a view model instance from Window resources.

NumPad control declares its own instance of view model

NumClickedCommand works with wrong data, not with the displayed object

make sure you have only one instance of view model

NumPad inherits DataContext and shouldn't create a new object and change DataContext

<UserControl x:Class="Billing.NumPad"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
         mc:Ignorable="d" Height="109" Width="248">

<Grid Height="109" VerticalAlignment="Top">
    <!--all Buttons here-->    
</Grid>

you are passing same viewmodel into numpadUser controll and mainWindow also as DataContext, so that will create new instance of viewmodel,so according to me you can use mainwindow's DataContext in NumPad also using Minwindow's GridName, you have to name your grid like

<Grid DataContext="{Binding Source={StaticResource ViewModel}}" x:Name="grdNumPad">

and you can access that DataContext in your NumPad.XAML this way

<Button Content="1" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="1" Command="{Binding DataContext.NumClickedCommand,ElementName=grdNumPad}"/>

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