2011-10-28 102 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的屬性。

相關問題