假设我有这样的类
public class R
{
protected string name;
protected List<S> listOfObjectS;
}
public class S
{
private string name, ID;
private A objectA;
}
public class A
{
private string name;
private int count;
}
如果用户打开了两个视图,一个显示R
的实例,另一个允许用户修改A
的实例,我需要在用户更改任何A
实例时更改R
的视图。
如果用户更改了A
实例的属性,传播该更改(通过S
实例)以使R
的所有实例都显示A
的新状态的最佳方法是什么?
编辑:彻底修改此答案以更具体地针对问题,因为标签显示您已经了解INotifyPropertyChanged
。
您需要在类 A
和类 S
中实现INotifyPropertyChanged
。使其只能通过一个属性来设置objectA
该属性将在 S 上引发 PropertyChanged
事件,只要在 A
中更改属性。例:
public class A : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
private int count;
public int Count
{
get { return count; }
set { count = value; OnPropertyChanged("Count"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
。和类S
...
public class S : INotifyPropertyChanged
{
private string name, ID;
private A objectA;
public A ObjectA
{
get { return objectA; }
set
{
var old = objectA;
objectA = value;
// Remove the event subscription from the old instance.
if (old != null) old.PropertyChanged -= objectA_PropertyChanged;
// Add the event subscription to the new instance.
if (objectA != null) objectA.PropertyChanged += objectA_PropertyChanged;
OnPropertyChanged("ObjectA");
}
}
void objectA_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Propagate the change to any listeners. Prefix with ObjectA so listeners can tell the difference.
OnPropertyChanged("ObjectA." + e.PropertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
对于类R
,请使用 ObservableCollection<S>
而不是 List<S>
,并订阅其 CollectionChanged
事件,并监视何时添加或删除对象以listOfObjectS
。添加后,订阅 S
的PropertyChanged
事件。然后更新了R
的视图。例:
public class R
{
protected string name;
protected System.Collections.ObjectModel.ObservableCollection<S> ListOfObjectS { get; private set; }
public R()
{
// Use ObservableCollection instead.
ListOfObjectS = new ObservableCollection<S>();
// Subscribe to all changes to the collection.
ListOfObjectS.CollectionChanged += listOfObjectS_CollectionChanged;
}
void listOfObjectS_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
// When items are removed, unsubscribe from property change notifications.
var oldItems = (e.OldItems ?? new INotifyPropertyChanged[0]).OfType<INotifyPropertyChanged>();
foreach (var item in oldItems)
item.PropertyChanged -= item_PropertyChanged;
}
// When item(s) are added, subscribe to property notifications.
if (e.Action == NotifyCollectionChangedAction.Add)
{
var newItems = (e.NewItems ?? new INotifyPropertyChanged[0]).OfType<INotifyPropertyChanged>();
foreach (var item in newItems)
item.PropertyChanged += item_PropertyChanged;
}
// NOTE: I'm not handling NotifyCollectionChangedAction.Reset.
// You'll want to look into when this event is raised and handle it
// in a special fashion.
}
void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.StartsWith("ObjectA."))
{
// Refresh any dependent views, forms, controls, whatever...
}
}
}
假设您有一个 form1,您可以在其中使用类 R 的实例来显示类 A 中的实例列表。然后按编辑,然后将同一类 A 的实例从类 R 实例发送到新窗体。
这将是对 R 实例中包含的对象的引用,因此会在 form2 中更新。您唯一需要做的就是刷新 form1 列表中的类 A 实例。
解释一下:当您使用类的对象实例调用窗体或方法时,这将创建一个引用,而不是克隆,因此可以从第二个 form2 更新。