如果您想了解ObservableCollection没有注意到其中的项目何时更改的相关知识,那么本文是一篇不可错过的文章,我们将对即使使用INotifyPropertyChanged进行全面详尽的解释
如果您想了解ObservableCollection 没有注意到其中的项目何时更改的相关知识,那么本文是一篇不可错过的文章,我们将对即使使用 INotifyPropertyChanged进行全面详尽的解释,并且为您提供关于.net – Observable Collections Collection已更改、C# INotifyPropertyChanged 实现、c# – INotifyPropertyChanged和ObservableCollection WPF、c# – WCF DataContracts中的INotifyPropertyChanged的有价值的信息。
本文目录一览:- ObservableCollection 没有注意到其中的项目何时更改(即使使用 INotifyPropertyChanged)
- .net – Observable Collections Collection已更改
- C# INotifyPropertyChanged 实现
- c# – INotifyPropertyChanged和ObservableCollection WPF
- c# – WCF DataContracts中的INotifyPropertyChanged
ObservableCollection 没有注意到其中的项目何时更改(即使使用 INotifyPropertyChanged)
有谁知道为什么这段代码不起作用:
public class CollectionViewModel : ViewModelBase { public ObservableCollection<EntityViewModel> ContentList { get { return _contentList; } set { _contentList = value; RaisePropertyChanged("ContentList"); //I want to be notified here when something changes..? //debugger doesn''t stop here when IsRowChecked is toggled } }}public class EntityViewModel : ViewModelBase{ private bool _isRowChecked; public bool IsRowChecked { get { return _isRowChecked; } set { _isRowChecked = value; RaisePropertyChanged("IsRowChecked"); } }}
ViewModelBase
包含RaisePropertyChanged
等的所有内容,并且它适用于除此问题之外的所有其他内容..
答案1
小编典典当您更改集合内的值时,不会调用 ContentList 的 Set
方法,而是应该注意CollectionChanged事件的触发。
public class CollectionViewModel : ViewModelBase{ public ObservableCollection<EntityViewModel> ContentList { get { return _contentList; } } public CollectionViewModel() { _contentList = new ObservableCollection<EntityViewModel>(); _contentList.CollectionChanged += ContentCollectionChanged; } public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { //This will get called when the collection is changed }}
好的,这是我今天两次被 MSDN 文档错误所困扰。在我给你的链接中,它说:
在添加、删除、更改、移动项目或刷新整个列表时发生。
但它实际上 不会 在更改项目时触发。我想你需要一个更暴力的方法:
public class CollectionViewModel : ViewModelBase{ public ObservableCollection<EntityViewModel> ContentList { get { return _contentList; } } public CollectionViewModel() { _contentList = new ObservableCollection<EntityViewModel>(); _contentList.CollectionChanged += ContentCollectionChanged; } public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Remove) { foreach(EntityViewModel item in e.OldItems) { //Removed items item.PropertyChanged -= EntityViewModelPropertyChanged; } } else if (e.Action == NotifyCollectionChangedAction.Add) { foreach(EntityViewModel item in e.NewItems) { //Added items item.PropertyChanged += EntityViewModelPropertyChanged; } } } public void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { //This will get called when the property of an object inside the collection changes }}
如果你需要这个很多,你可能想要子类化你自己的子类ObservableCollection
,CollectionChanged
当成员PropertyChanged
自动触发其事件时触发事件(就像它在文档中所说的那样......)
.net – Observable Collections Collection已更改
ObservabelCollection<Person> personcollection... and if I change a property like: Person p = personcollection.where(e => e.FirstName == "Joey").FirstOrDefault(); if (p != null) { p.FirstName = "Joe"; }
我希望在UI中发生一些事情,但没有任何改变.
任何帮助将不胜感激.
大卫
解决方法
它并不关心它的集合中某个对象的属性是否发生变化.您需要在这些对象的属性上实现INotifyPropertyChanged接口以触发对UI的更改.
我读了here,给了我一些有用的见解.虽然它针对WPF,但大多数仍然适用,因为Silverlight本质上是WPF的一个子集.
以及这篇MSDN文章,其中指出:
In particular,if you are using OneWay or TwoWay (for example,you want your UI to update when the source properties change dynamically),you must implement a suitable property changed notification mechanism such as the INotifyPropertyChanged interface.
C# INotifyPropertyChanged 实现
INotifyPropertyChanged:
该接口包含一个事件, 针对属性发生变更时, 执行该事件发生。
//
// 摘要:
// 通知客户端属性值已更改。
public interface INotifyPropertyChanged
{
//
// 摘要:
// 在属性值更改时发生。
event PropertyChangedEventHandler PropertyChanged;
}
接下来, 用一个简单的示例说明其简单使用方法(大部分常用的做法演示):
1.定义一个ViewModelBase 继承INotifyPropertyChanged 接口, 添加一个虚函数用于继承子类的属性进行更改通知
2.MainViewModel中两个属性, Code,Name 进行了Set更改时候的调用通知,
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainViewModel : ViewModelBase
{
private string name;
private string code;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
public string Code
{
get { return code; }
set { code = value; OnPropertyChanged("Code"); }
}
}
正如上面的代码, 应该注意到了, 每个属性调用OnPropertyChanged的时候, 都需要传一个自己的属性名, 这样是不是很多余?对, 很多余。
改造
1.看到有些文章给基类的参数修改为表达式树, 这样实现的时候,传递一个Lambda表达式, 我觉得这是不治标不治本吗?如下:
说明: 原来直接传递一个固定的string类型实参, 不说换成lambda的性能问题, 同样带来的问题你还是固定的需要去书写这个参数。 不建议这么做!
CallerMemberName
该类继承与 Attribute, 不难看出, 该类属于定义在方法和属性上的一种特效类, 实现该特性允许获取方法调用方的方法或属性名称
//
// 摘要:
// 允许获取方法调用方的方法或属性名称。
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class CallerMemberNameAttribute : Attribute
{
//
// 摘要:
// 初始化 System.Runtime.CompilerServices.CallerMemberNameAttribute 类的新实例。
public CallerMemberNameAttribute();
}
改造ViewModelBase:
改造之后, 是不是发现明显区别:
不用传递参数, 不用书写lambda表达式, 也不用担心其传递的参数安全, 直接根据读取属性名!
c# – 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,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>(); }
解决方法
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.请注意,您无法使用自动实现的属性执行此操作,因为您需要在setter中添加自定义逻辑.
c# – WCF DataContracts中的INotifyPropertyChanged
为了避免将DataContract类复制到客户端类,他们希望合同支持INotifyPropertyChanged.
但是,我有一些客户端是MVC3客户端.
添加INotifyPropertyChanged支持数据合同会搞砸他们吗?
另外,我打算让我的DataContracts也成为我的Entity Framework数据库连接的POCO对象.将INotifyPropertyChanged搞砸了吗?
或者INotifyPropertyChanged只是一个WPF的东西,其他的应用程序将不关心它?
解决方法
Or is INotifyPropertyChanged just a WPF thing and the other apps won’t care about it?
INotifyPropertyChanged只是一个可以在您的实体上实现的界面,而不会弄乱任何东西.它主要用于WPF和Silverlight,它不会对不使用它的其他技术产生影响.因此,在WCF数据协定上实现它不应该有任何问题.虽然请注意,当您从此WCF服务生成强类型客户端代理(使用svcutil.exe或添加服务引用)时,生成的实体将不会实现此接口.他们将是POCO.
今天关于ObservableCollection 没有注意到其中的项目何时更改和即使使用 INotifyPropertyChanged的分享就到这里,希望大家有所收获,若想了解更多关于.net – Observable Collections Collection已更改、C# INotifyPropertyChanged 实现、c# – INotifyPropertyChanged和ObservableCollection WPF、c# – WCF DataContracts中的INotifyPropertyChanged等相关知识,可以在本站进行查询。
本文标签: