INotifyPropertyChanged и ObservableCollection WPF - PullRequest
3 голосов
/ 28 октября 2011

Прямо сейчас у меня есть календарь, который показывает только один месяц (какой бы месяц я ни проходил). Я пытаюсь позволить пользователю выбрать, какой месяц и год из comboBox и получить обновление календаря. Я связываюсь, используя observablecollection, с которым я вроде как знаком. Я понятия не имею, как работает INotifyPropertyChanged. Я никогда не использовал это раньше. Любая помощь или совет с благодарностью. Это то, что я до сих пор:

public class Schedule : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void Update(int propertyName)
    {
        if (propertyName != null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                 handler.Invoke(this, new PropertyChangedEventArgs(propertyName.ToString()));
        }
    }


   // public void UpdateCal(PropertyChangedEventArgs e)
   // {
    //    if (PropertyChanged != null)
    //        PropertyChanged(this, e);
  //  } 
    public string MonthWeek { get; set; }
    public string Year { get; set; }
    public string Month { get; set; }
    public string day { get; set; }
    public string WeekOfYear { get; set; }
    public string dayofweek { get; set; }

   // public string month {
    //    get {return Month; }
    //    set
    //    {
     //       UpdateCal(new PropertyChangedEventArgs("month"));
      //  }
   // }
    public int WeekNo { get; set; }
    public int WeekDay { get; set; }
    public DateTime Date { get; set; }
 }

--- Это еще один класс, который определяет, где разместить каждую дату в сетке ----

           public SchedulePage(MainWindow parentForm)
    {
        InitializeComponent();

        pick = Convert.ToInt32(comboMonth.SelectedItem) + 1;
        _parentForm = parentForm;
        // DateTime date = new DateTime(year, month, day);
        var t = new List<Schedule>();
        DateTime curr = DateTime.Now;
      //  comboMonth.Items.Add(curr.Month);
        DateTime newcurr = new DateTime(2011, pick, 1);
     //   pickdate = datePickercal.SelectedDate;
      //  DateTime newcurr = new DateTime(curr.Year, curr.Month, 1);
        var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
        var ms = cal.GetWeekOfYear(new DateTime(newcurr.Year, newcurr.Month, 1), System.Globalization.CalendarWeekRule.FirstDay, System.DayOfWeek.Sunday);
        for (var i = 1; newcurr.Month == pick; newcurr = newcurr.AddDays(1))
        {
            var sched = new Schedule();
            var month_week = (newcurr.Day / 7) ;
            sched.MonthWeek = newcurr.GetWeekOfMonth().ToString();
            sched.Month = newcurr.Month.ToString();
            sched.Year = newcurr.Year.ToString();
            sched.day = newcurr.Day.ToString();
            sched.WeekOfYear = cal.GetWeekOfYear(newcurr, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString();
            sched.dayofweek = newcurr.DayOfWeek.ToString();
            t.Add(sched);

                _parentForm.bindings.schedule.Add(new Schedule { WeekNo = newcurr.GetWeekOfMonth()-1, WeekDay = (int)newcurr.DayOfWeek, day = newcurr.Day.ToString() });

        }
        lblDate.Content = (newcurr.Month -1) + "/" + newcurr.Year;

         DataContext = _parentForm.Bindings;

--- И этот класс делает наблюдаемые коллекции -----

           public partial class BindingCamper 
{  // This class assist in binding campers from listview to the textboxes on the camperspage
    public ObservableCollection<Camper> Campers { get; set; }
    public ObservableCollection<Staff> StaffMembers { get; set; }
    public ObservableCollection<Schedule> schedule { get; set; }
    public BindingCamper()
    {
        Campers = new ObservableCollection<Camper>();
      StaffMembers = new ObservableCollection<Staff>();
      schedule = new ObservableCollection<Schedule>();
    }

Ответы [ 3 ]

5 голосов
/ 29 октября 2011

При связывании со свойством (даже если это свойство является ObservableCollection), любые изменения СОБСТВЕННОСТИ (не содержимого свойства) должны вызывать событие PropertyChanged.

ObservableCollection самодостаточен, когда дело доходит до вызова события CollectionChanged, поэтому не беспокойтесь о запуске события для самих элементов ItemsSource.

XAML:

<!-- This says that ItemsSource is bound to the Campers property... -->
<ItemsControl ItemsSource="{Binding Path=Campers, Mode=OneWay}" />

КЛАСС:

public class TheViewModel()
{
   private ObservableCollection<Camper> _campers;
   public ObservableCollection<Camper> Campers
   {
       get { return _campers; }
       set
       {
           if (Equals(_campers, value)) return;

           _campers = value;
           RaisePropertyChanged("Campers"); //Or however you implement it
       }
   }

   private void SomeFunc()
   {
       var bindingCamper = new BindingCamper();

       Campers = bindingCamper.Campers; //This will fire the event
       //etc.
   }

}


В качестве альтернативы, если вы BindingCamper - это ваша ViewModel, тогда вместо этого вы делаете то же самое.

5 голосов
/ 29 октября 2011

Так вы обычно реализуете INotifyPropertyChanged:

public class Schedule : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

    private string _monthWeek;
    public string MonthWeek
    {
        get { return _monthWeek; }
        set
        {
            if (value != _monthWeek)
            {
                _monthWeek = value;
                OnPropertyChanged("MonthWeek");
            }
        }
    }

    // And so on for other properties...

}

По сути, вам просто нужно запускать событие PropertyChanged каждый раз, когда свойство обновляется, поэтому каждый установщик должен вызывать OnPropertyChanged. Обратите внимание, что вы не можете сделать это с автоматически внедряемыми свойствами, так как вам нужно добавить пользовательскую логику в установщик.

2 голосов
/ 29 октября 2011

Когда вы изменяете свойство из кода и хотите обновить свой пользовательский интерфейс, вы используете интерфейс INotifyPropertyChanged.Как я вижу, вы реализовали интерфейс и даже настроили помощника для его использования, просто вы использовали int в качестве параметра, вместо этого вы должны использовать строку.Если вы установили свойство, просто позвоните своему помощнику с правильным PropertyName, и все готово.

Примерно так:

 public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

И чтобы вызвать событие, чтобы уведомить пользовательский интерфейс:

NotifyPropertyChanged("YourPropertyName");

Может быть, вам потребуется установить привязку TwoWay, но это толькоtrue, если вы тоже хотите изменить свойство из пользовательского интерфейса.

...