简体   繁体   中英

Why Mvvm approach is not working for my Calculator?

I am trying to work on MVVM using silverlight 5 and my xaml code is this:

 <Grid x:Name="LayoutRoot" Background="White" Height="100" Width="350">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
       <TextBox Grid.Column="0" Text="{Binding FirstValue, Mode=TwoWay}" Height="25" TextAlignment="Right"/>
        <TextBlock Grid.Column="1" Text="+" Height="25" TextAlignment="Center"/>
        <TextBox Grid.Column="2" Text="{Binding SecondValue, Mode=TwoWay}" Height="25" TextAlignment="Right"/>
        <TextBlock Grid.Column="3" Text="=" Height="25" TextAlignment="Center"/>
        <TextBlock Grid.Column="4" Text="{Binding Result, Mode=OneWay}" Height="25" TextAlignment="Left"/>
        <Button Grid.Row="1" Grid.ColumnSpan="5" Margin="0,5,0,0" Content="Calculate" Command="{Binding CalculateCommand}"  />
    </Grid>

And

public MainPage()
        {
            InitializeComponent();
            this.DataContext = new CalculatorViewModel();
        }

My CalculatorViewModel.cs class is :

public class CalculatorViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public CalculatorModel cc;


        private string _firstValue;
        public string FirstValue
        {
            get { return _firstValue; }
            set
            {
                _firstValue = value;
                OnPropertyChanged("FirstValue");
            }
        }

        private string _secondValue;
        public string SecondValue
        {
            get { return _secondValue; }
            set
            {
                _secondValue = value;
                OnPropertyChanged("SecondValue");
            }
        }

        private string _result;
        public string Result
        {
            get { return _result; }
            private set
            {
                _result = value;
                OnPropertyChanged("Result");
            }
        }

        private ICommand _calculateCommand;
        public ICommand CalculateCommand
        {
            get { return _calculateCommand; }
        }

        public CalculatorViewModel()
        {
            cc = new CalculatorModel();
            cc.FirstValue = _firstValue;
            cc.SecondValue = _secondValue;
            cc.Result = _result;
            _calculateCommand = new RelayCommand(cc.Calculate) { IsEnabled = true };
            //This Calculate() is defined in Model class (CalculatorModel.cs).
         }    

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
            }
        }

    }

And i wanted to define this calculate delegate in Model class(CalculatorModel.cs).According to what i understand this is what for Model class are meant. ( please correct me if i am wrong ).

I done like this:

 public class CalculatorModel
    {
        #region PROPERTIES
        public string FirstValue;
        public string SecondValue;
        public string Result;

        #endregion
        //CalculatorViewModel cv = new CalculatorViewModel();

        public CalculatorModel()
        {
            this.Result = "";
            this.FirstValue = "";
            this.SecondValue = "";              
        }
        public void Calculate()
        {
            MessageBox.Show("check : " +FirstValue);
            Result = (Convert.ToInt32(FirstValue) + Convert.ToInt32(SecondValue)).ToString();
        }
    }

The problem is i dont know why on debugging the value of Result, FirstValue and SecondValue are null the delegate calculate() is called on button click but there is no output updated in Result.

Could some one please correct me whats wrong in my approach of defining calculate() in Model class ?

You don't seem to be updating the values in the Model. Databinding only works between View and ViewModel.

    private string _firstValue;
    public string FirstValue
    {
        get { return _firstValue; }
        set
        {
            _firstValue = value;
            cc.FirstValue = _firstValue;     // add this
            OnPropertyChanged("FirstValue");
        }
    }

and do that for SecondValue as well. Change the command so that the result is assigned to Result.

This tells you that your setup is not the most efficient or elegant. Consider

  1. Make the Model INotifyPropertyChanged and bind to Model.FirstValue
  2. or, drop the concept of a Model here.

When you make the Model implement INPC you can (should) remove the FirstValue, SecondValue and Result entirely from the VM. You can bind to the Model: Text="{Binding Path=cc.FirstValue, Mode=TwoWay}" and then make the Model a property:

   public CalculatorModel cc { get; set; }   // must be a property

Otherwise, the better pattern for 'repeating' a property is:

    //private string _firstValue;
    public string FirstValue
    {
        get { return cc.FirstValue; }
        set
        {
            //_firstValue = value;
            cc.FirstValue = value;           // add this
            OnPropertyChanged("FirstValue");
        }
    }

avoid storing data twice.

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