WPF/C# 将 ObservableCollection 中项目的属性更改更新到 ListBox
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18731608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF / C# Updating property change of an item in an ObservableCollection to the ListBox
提问by B.K.
I have a list box:
我有一个列表框:
<ListBox x:Name="lbxAF" temsSource="{Binding}">
that gets its data from this from this modified Observable Collection:
从这个修改过的 Observable 集合中获取它的数据:
public ObservableCollectionEx<FileItem> folder = new ObservableCollectionEx<FileItem>();
which is created within a class that uses FileSystemWatcher to monitor a specific folder for addition, deletion and modification of files.
它是在使用 FileSystemWatcher 监视特定文件夹以添加、删除和修改文件的类中创建的。
The ObservableCollection was modified (hence the Ex at the end) so that I can modify it from an outside thread (code is not mine, I actually did some searching through this website and found it, works like a charm):
ObservableCollection 被修改(因此最后是 Ex),以便我可以从外部线程修改它(代码不是我的,我实际上在这个网站上做了一些搜索并找到了它,就像一个魅力):
// This is an ObservableCollection extension
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
// Override the vent so this class can access it
public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
using (BlockReentrancy())
{
System.Collections.Specialized.NotifyCollectionChangedEventHandler eventHanlder = CollectionChanged;
if (eventHanlder == null)
return;
Delegate[] delegates = eventHanlder.GetInvocationList();
// Go through the invocation list
foreach (System.Collections.Specialized.NotifyCollectionChangedEventHandler handler in delegates)
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
// If the subscriber is a DispatcherObject and different thread do this:
if (dispatcherObject != null && dispatcherObject.CheckAccess() == false)
{
// Invoke handler in the target dispatcher's thread
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e);
}
// Else, execute handler as is
else
{
handler(this, e);
}
}
}
}
}
The collection is made up of these:
该系列由以下组成:
public class FileItem
{
public string Name { get; set; }
public string Path { get; set; }
}
which allow me to store names and paths of files.
这允许我存储文件的名称和路径。
Everything works great as far as deletion and addition of files, and the List Box gets updated flawlessly with respect to those two... however, if I change the name of any of the files, it doesn't update the list box.
就文件的删除和添加而言,一切都很好,并且列表框在这两个方面得到了完美的更新......但是,如果我更改任何文件的名称,它不会更新列表框。
How would I notify list box of the changes in FileItem's properties? I assumed that ObservableCollection would handle that, but apparently it raises flag only when FileItem is added or deleted, not when its contents are changed.
我如何将 FileItem 的属性更改通知列表框?我认为 ObservableCollection 会处理这个问题,但显然它只有在添加或删除 FileItem 时才会引发标志,而不是在其内容发生变化时。
采纳答案by Anand Murali
Your FileItem
class should implement INotifyPropertyChanged
. Below is a simple working implementation of it.
你的FileItem
班级应该实现INotifyPropertyChanged
. 下面是它的一个简单的工作实现。
public class FileItem : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set {
if (_Name != value)
{
_Name = value;
OnPropertyChanged("Name");
}
}
}
private string _Path;
public string Path
{
get { return _Path; }
set {
if (_Path != value)
{
_Path = value;
OnPropertyChanged("Path");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
回答by New Dev
That's how the ObservableCollection
works - it monitors only insertion/deletion/moving of items.
这就是ObservableCollection
工作原理 - 它仅监控项目的插入/删除/移动。
To update the View when each item (or FileItem
, in your case) changes, the FileItem
must implement INotifyPropertyChanged
and fire the appropriate event when you set each property that you want to observe.
要在每个项目(或FileItem
在您的情况下)更改时更新视图,FileItem
必须INotifyPropertyChanged
在您设置要观察的每个属性时实现并触发适当的事件。
Here's an example of how to do this: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
以下是如何执行此操作的示例:http: //msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
回答by Berezh
Try this simple one:
试试这个简单的:
public class NotifyObservableCollection<TItem> : ObservableCollection<TItem>
where TItem : class , INotifyPropertyChanged, new()
{
#region Fields
private Action _itemPropertyChanged;
#endregion
#region Constructor
public NotifyObservableCollection(Action itemPropertyChanged)
{
_itemPropertyChanged = itemPropertyChanged;
}
#endregion
#region Methods
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
var notifyItem = item as INotifyPropertyChanged;
if (notifyItem != null)
{
notifyItem.PropertyChanged += ItemPropertyChanged;
}
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var item in e.OldItems)
{
var notifyItem = item as INotifyPropertyChanged;
if (notifyItem != null)
{
notifyItem.PropertyChanged -= ItemPropertyChanged;
}
}
}
base.OnCollectionChanged(e);
}
#endregion
#region Private Methods
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(_itemPropertyChanged!=null)
{
_itemPropertyChanged();
}
}
#endregion
}