INotifyPropertyChanged 和 ObservableCollection WPF

发布于 2024-12-12 19:55:30 字数 3661 浏览 5 评论 0原文

现在我有一个日历,只显示一个月(我进入的月份)。我试图让用户从组合框中选择月份和年份并更新日历。我正在使用我熟悉的 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>();
    }

Right now I have a calender that only displays one month(what ever month I pass in). I'm trying to let the user pick what month and year from a comboBox and have the calender update. I'm binding using observablecollection which I'm sort of familiar with. I have no clue how INotifyPropertyChanged works though. I've never used it before. Any help or advice is greatly appreciated. This is what I have so far:

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

---This is another class that figures out where to place each date on the grid----

           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;

---And this class makes the 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>();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月下伊人醉 2024-12-19 19:55:30

这就是您通常实现 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 事件,因此每个 setter 都必须调用 OnPropertyChanged代码>.请注意,您无法使用自动实现的属性来执行此操作,因为您需要在设置器中添加自定义逻辑。

This is how you typically implement 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...

}

Basically, you just need to trigger the PropertyChanged event every time a property is updated, so every setter must call OnPropertyChanged. Note that you can't do it with auto-implemented properties, since you need to add custom logic in the setter.

暗地喜欢 2024-12-19 19:55:30

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

在引发 CollectionChanged 事件时,ObservableCollection 是独立的,因此不必担心为 ItemsSource 项本身触发事件。

XAML:

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

CLASS:

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,那么您可以在其中执行相同的操作。

When you bind to a property (even if that property is an ObservableCollection), any changes to the PROPERTY (not the contents of the property) should raise the PropertyChanged event.

An ObservableCollection is self-contained when it comes to raising the CollectionChanged event, so don't worry about firing off an event for the ItemsSource items themselves.

XAML:

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

CLASS:

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.
   }

}


Alternatively, if your BindingCamper is your ViewModel then you do the same thing in there instead.

握住你手 2024-12-19 19:55:30

当您从代码后面更改属性并且想要更新 UI 时,您可以使用 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");

也许您还需要设置 TwoWay 绑定,但只有当您也想从 UI 更改属性时才如此。

When you change a property from code behind and you wanna update your UI then you use INotifyPropertyChanged inteface. As i see you implemented the interface and even set up a helper to use it just you used an int as parameter you should use a string instead. If you set the property then just call your helper with the right PropertyName and you are good to go.

Like this:

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

And to trigger the event to notify the UI:

NotifyPropertyChanged("YourPropertyName");

Maybe you will need to set the TwoWay binding too but that's only true if you wanna change the property from the UI too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文