Pan*_*oul 39 c# collections wpf observablecollection inotifypropertychanged
我在这个链接上找到了
ObservableCollection没有注意到它中的Item何时发生变化(即使使用INotifyPropertyChanged)
一些通知Observablecollection项目已更改的技术.这个链接中的TrulyObservableCollection似乎正是我正在寻找的.
public class TrulyObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public TrulyObservableCollection()
: base()
{
CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
}
void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Object item in e.NewItems)
{
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
}
}
if (e.OldItems != null)
{
foreach (Object item in e.OldItems)
{
(item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
}
}
}
void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
OnCollectionChanged(a);
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试使用它时,我没有收到有关该集合的通知.我不知道如何在我的C#代码中正确实现它:
XAML:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MyItemsSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
ViewModel:
public class MyViewModel : ViewModelBase
{
private TrulyObservableCollection<MyType> myItemsSource;
public TrulyObservableCollection<MyType> MyItemsSource
{
get { return myItemsSource; }
set
{
myItemsSource = value;
// Code to trig on item change...
RaisePropertyChangedEvent("MyItemsSource");
}
}
public MyViewModel()
{
MyItemsSource = new TrulyObservableCollection<MyType>()
{
new MyType() { MyProperty = false },
new MyType() { MyProperty = true },
new MyType() { MyProperty = false }
};
}
}
public class MyType : ViewModelBase
{
private bool myProperty;
public bool MyProperty
{
get { return myProperty; }
set
{
myProperty = value;
RaisePropertyChangedEvent("MyProperty");
}
}
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行程序时,我将3复选框设置为false,true,false,如属性初始化.但是当我改变其中一个ckeckbox的状态时,程序会通过item_PropertyChanged但从不在MyItemsSource属性代码中.
Rac*_*hel 81
您评论过的位置// Code to trig on item change...
仅在集合对象发生更改时触发,例如当它设置为新对象或设置为null时.
使用您当前的TrulyObservableCollection实现,要处理集合中属性更改的事件,请注册CollectionChanged
事件MyItemsSource
public MyViewModel()
{
MyItemsSource = new TrulyObservableCollection<MyType>();
MyItemsSource.CollectionChanged += MyItemsSource_CollectionChanged;
MyItemsSource.Add(new MyType() { MyProperty = false });
MyItemsSource.Add(new MyType() { MyProperty = true});
MyItemsSource.Add(new MyType() { MyProperty = false });
}
void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Handle here
}
Run Code Online (Sandbox Code Playgroud)
我个人真的不喜欢这个实现.您正在提出一个CollectionChanged
事件,表示整个集合已经重置,只要房产发生变化.当然,它会在集合中的项目发生变化时随时更新UI,但我发现性能不佳,并且它似乎无法识别哪些属性发生了变化,这是关键信息之一在做某事时我通常需要PropertyChanged
.
我更喜欢使用常规ObservableCollection
,只是将PropertyChanged
事件连接到它的项目上CollectionChanged
.如果您的UI正确绑定到其中的项目,则ObservableCollection
当集合中项目的属性发生更改时,您无需告知UI更新.
public MyViewModel()
{
MyItemsSource = new ObservableCollection<MyType>();
MyItemsSource.CollectionChanged += MyItemsSource_CollectionChanged;
MyItemsSource.Add(new MyType() { MyProperty = false });
MyItemsSource.Add(new MyType() { MyProperty = true});
MyItemsSource.Add(new MyType() { MyProperty = false });
}
void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach(MyType item in e.NewItems)
item.PropertyChanged += MyType_PropertyChanged;
if (e.OldItems != null)
foreach(MyType item in e.OldItems)
item.PropertyChanged -= MyType_PropertyChanged;
}
void MyType_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "MyProperty")
DoWork();
}
Run Code Online (Sandbox Code Playgroud)
小智 9
我通过使用静态Action解决了这种情况
public class CatalogoModel
{
private String _Id;
private String _Descripcion;
private Boolean _IsChecked;
public String Id
{
get { return _Id; }
set { _Id = value; }
}
public String Descripcion
{
get { return _Descripcion; }
set { _Descripcion = value; }
}
public Boolean IsChecked
{
get { return _IsChecked; }
set
{
_IsChecked = value;
NotifyPropertyChanged("IsChecked");
OnItemChecked.Invoke();
}
}
public static Action OnItemChecked;
}
public class ReglaViewModel : ViewModelBase
{
private ObservableCollection<CatalogoModel> _origenes;
CatalogoModel.OnItemChecked = () =>
{
var x = Origenes.Count; //Entra cada vez que cambia algo en _origenes
};
}
Run Code Online (Sandbox Code Playgroud)
一个简单的解决方案是使用BindingList<T>
而不是ObservableCollection<T>
. 事实上,BindingList 中继项更改通知。因此,对于绑定列表,如果项目实现了接口,INotifyPropertyChanged
那么您可以使用ListChanged 事件简单地获取通知。
另请参阅此SO 答案。
归档时间: |
|
查看次数: |
118087 次 |
最近记录: |