2011-10-28 58 views
3

现在我有一个日历只显示一个月(我通过的月份)。我试图让用户从comboBox中选择月份和年份,并进行日历更新。我使用我熟悉的observablecollection进行绑定。我不知道INotifyPropertyChanged是如何工作的。我从来没有用过它。任何帮助或建议,不胜感激。这是我到目前为止有:INotifyPropertyChanged和ObservableCollection WPF

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; 

---而这一类使得observablecollections -----

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

回答

5

这是你通常如何实现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。请注意,您无法使用自动实现的属性来完成此操作,因为您需要在设置器中添加自定义逻辑。

+0

你可以用自动实现的属性来实现,但建议不要这样做。最好自己包含OnPropertyChanged,而不是依靠代码来改变它们来触发它。虽然,这实际上只适用于OneWay属性,因为UI不应该能够触发OnPropertyChanged。 –

+0

@ m-y - 如何使用自动实现的属性实现INotifyPropertyChanged? – CodeNaked

+0

@my,当然,您可以从课程中的任何位置调用OnPropertyChanged,但在这种情况下,不能保证会引发该事件(例如,如果该属性是从课外更新的) –

4

当您绑定到一个属性(即使该属性是一个ObservableCollection)时,对属性(而不是属性内容)的任何更改都会引发PropertyChanged事件。

当涉及到引发CollectionChanged事件时,ObservableCollection是自包含的,因此不必担心为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 您的视图模型,然后你在那里做同样的事情代替。

2

当你从后面的代码更改一个属性,你想更新你的用户界面,然后你使用INotifyPropertyChanged接口。正如我看到你实现了接口,甚至设置一个帮助器来使用它,只是你使用了一个int作为参数,你应该使用一个字符串来代替。如果你设置了属性,那么只需使用正确的PropertyName调用你的助手,你就可以走了。

像这样:

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

而触发的事件,通知UI:

NotifyPropertyChanged("YourPropertyName"); 

也许你会需要设置双向绑定太多,但如果你想改变这是唯一真正的也来自UI的属性。

相关问题