[英]ObservableCollection not updating through INotifyPropertyChanged
[英]Updating ObservableCollection Item properties using INotifyPropertyChanged
檢查以確保我的假設是正確的。
我有一個ObservableCollection類。 我正在調用Web服務並檢索一組設備。 然后我枚舉ObservableCollection並將每個項目設置為從Web服務檢索到的相應設備。 我所感到的設備具有與ObservableCollection中的項不同的屬性值,但PropertyChanged事件未觸發。
我假設這是ByDesign,並且為了讓PropertyChanged事件觸發,我實際上必須枚舉每個屬性並設置值?
例如,在下面的情況中,任何Device類屬性都不會觸發PropertyChanged事件。
ObservableCollection<Device> Items = new ObservableCollection<Device>();
Items = LoadItems();
List<Device> devices = GetDevices();
foreach (var item in Items)
{
var currentDevice = devices.Single(d1 => d1.ID == item.ID);
item = currentDevice;
}
但是,如果我手動更新每個屬性,我就是在做生意:
ObservableCollection<Device> Items = new ObservableCollection<Device>();
Items = LoadItems();
List<Device> devices = GetDevices();
foreach (var item in Items)
{
var currentDevice = devices.Single(d1 => d1.ID == item.ID);
item.Latitude = currentDevice.Latitude;
item.Longitude= currentDevice.Longitude;
}
在上面的案例中,緯度和經度都會觸發他們的事件。
既然我的班級有很多屬性,那么還有一個更好的方法嗎?
在第一個示例中,設置集合中的項目將觸發CollectionChanged事件,而不是單個項目的PropertyChanged事件。
您可以通過為PropertyChanged事件指定空字符串來通知所有屬性。 例如:
item.RaisePropertyChanged("");
其中RaisePropertyChanged是一個調用INotifyPropertyChanged實現的PropertyChanged事件的公共方法。
為此,Load方法可能很有用,因此您不會覆蓋引用,而是設置舊對象的所有屬性。 這是我剛剛寫的一個通用擴展方法,它將分配所有可寫屬性,它非常粗糙:
public static class ExtensionMethods
{
public static void Load<T>(this T target, Type type, T source, bool deep)
{
foreach (PropertyInfo property in type.GetProperties())
{
if (property.CanWrite && property.CanRead)
{
if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
{
property.SetValue(target, property.GetValue(source, null), null);
}
else
{
object targetPropertyReference = property.GetValue(target, null);
targetPropertyReference.Load(targetPropertyReference.GetType(), property.GetValue(source, null), deep);
}
}
}
}
}
然后你應該可以打電話
item.Load(item.GetType(), currentDevice, true); //false for shallow loading
分配所有值(如果它們是屬性)。
編輯:使方法遞歸,因此它將為不屬於基本類型或值類型(或字符串)的屬性調用Load
。 在某些情況下可能仍然行為不端。
你還可以添加一個布爾deep
的方法和控制是否應該深負載如果可能需要的。 (只需添加|| !deep
到那個長if-expression)
注意:如果您願意,您當然也可以覆蓋對象引用並使用反射來為所有不同的屬性引發PropertyChanged事件。 無論哪種方式,您都不需要手動處理每個屬性。
Edit2:因為PropertyInfo.GetValue
返回一個object
我以前的代碼沒有遞歸加載,不幸的是,你必須顯式傳遞一個Type,請參閱舊版本的修訂版。
編輯3:如果沒有類型參考使這項工作的方法看到我問的這個專門的問題 。 但是,這並未解決其他問題,如循環引用和枚舉對象的屬性。
我認為你可以重載=
運算符並在那里進行屬性賦值。 然后將生成PropertyChanged事件,您仍將使用與第一個示例中相同的語法。
Device類必須實現接口INotifyPropertyChanged。然后為每個屬性觸發notify屬性更改事件asuall。
這將自動啟用屬性更改通知。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.