简体   繁体   中英

TwoWay binding not working with datepicker MVVM

I've finally managed to get started with MVVM and implementing INotifyPropertyChanged and I am facing the following problem: Even though I pass the month from my datepicker as a parameter to my query, the result of my query doesn't change if I choose a different month.

I was hoping INotifyPropertyChanged would take care of that. How do I make sure that my Efficiency changes when picking a different month from the datepicker?

Thank you

ViewModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Location.Model;
using System.Windows.Controls;

namespace Location.ViewModel
{
    public class LocationViewModel: INotifyPropertyChanged
    {


        public LocationViewModel()
        {
            var month = 0;
            int.TryParse(MDate.ToString("MM"), out month);
            var db = new DailyEntities();
            Efficiency = Convert.ToDecimal(db.LocationKPI.Where(a => a.sMonth == month).Select(a => a.Efficiency).FirstOrDefault());
        }

        private DateTime _mDate = DateTime.Now;

        public DateTime MDate
        {
            get { return _mDate; }
            set { _mDate = value; OnPropertyChanged("MDate"); }
        }

        decimal efficiency;

        public decimal Efficiency
        {
            get { return efficiency; }
            set
            {
                efficiency = value;
                OnPropertyChanged("Efficiency");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

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

View

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new LocationViewModel();
    }
}

XAML

<DatePicker x:Name="vDatePick" SelectedDateChanged="vDatePick_SelectedDateChanged" SelectedDate="{Binding MDate, Mode=TwoWay}" Text="Pick date"/>

You need state that Efficiency must be updated when MDate is

public DateTime MDate
{
   get { return _mDate; }
   set 
   { 
       _mDate = value; 
       OnPropertyChanged("MDate"); 
       OnPropertyChanged("Efficiency"); 
   }
}

I would also put the query for Efficiency in the getter and remove the setter. Which in turn would mean you no longer need the private variable efficiency and you would remove the query in the constructor.

public decimal Efficiency
{
    get 
    {
        var month = 0;
        int.TryParse(MDate.ToString("MM"), out month);
        return Convert.ToDecimal(
            db.LocationKPI
                .Where(a => a.sMonth == month)
                .Select(a => a.Efficiency)
                .FirstOrDefault());
    }
}

EDIT: Updated Efficiency getter and setter

EDIT: Wanted to note you should probably set MDate to a default value in your constructor as well if you wanted to see results when the page loads.

The reason it isn't working is because in your ViewModel, you are only executing the code to set the efficiency in the constructor. You need to create a method and then call it from the constructor and the set of MDate, so Efficiency will be updated each time MDate changes:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Location.Model;
using System.Windows.Controls;

namespace Location.ViewModel
{
    public class LocationViewModel: INotifyPropertyChanged
    {
        public LocationViewModel()
        {
            SetEfficiency();
        }

        private DateTime _mDate = DateTime.Now;

        public DateTime MDate
        {
            get { return _mDate; }
            set 
            {
                _mDate = value;
                OnPropertyChanged("MDate");
                SetEfficiency();
            }
        }

        decimal efficiency;

        public decimal Efficiency
        {
            get { return efficiency; }
            set
            {
                efficiency = value;
                OnPropertyChanged("Efficiency");
            }
        }

        DailyEntities db = new DailyEntities();

        private void SetEfficiency()
        {
            var month;
            int.TryParse(MDate.ToString("MM"), out month);
            Efficiency = Convert.ToDecimal(db.LocationKPI.Where(a => a.sMonth == month).Select(a => a.Efficiency).FirstOrDefault());
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

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