Search code examples
c#wpfmvvmdatepickerentity

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"/>

Solution

  • 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));
            }
        }
    }