2013-09-11 132 views
2

我有一个列表框:WPF/C#更新属性更改到ListBox

<ListBox x:Name="lbxAF" temsSource="{Binding}"> 

,从这个来自这个修改观察到的集合中获取数据:

public ObservableCollectionEx<FileItem> folder = new ObservableCollectionEx<FileItem>(); 

它是在使用FileSystemWatcher监视特定文件夹以添加,删除和修改文件的类中创建的。

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); 
        } 
       } 
      } 
     } 
    } 

收集是由这些:

public class FileItem 
{ 
    public string Name { get; set; } 
    public string Path { get; set; } 
} 

这让我保存的文件名称和路径。

一切都很正常,只要删除和添加文件和列表框获取相对于完美更新,以这两个......然而,如果我改变任何文件的名称,它不更新列表框。

我该如何通知FileItem属性更改的列表框?我认为ObservableCollection会处理这个问题,但显然它只会在FileItem被添加或删除时引发标志,而不是在其内容被更改时引发标志。

+0

您的FileItem不执行INotifiyPropertyChanged ...还你怎么在视图模型/代码隐藏文件名的更新? – Nitin

回答

7

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)); 
    } 


} 
2

这就是ObservableCollection的工作原理 - 它只监视项目的插入/删除/移动。

更新视图时,每个项目(或FileItem,你的情况)的变化,当您设置要观察每个属性FileItem必须实现INotifyPropertyChanged,并触发相应的事件。

下面是如何做到这一点的例子:http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

+0

我该怎么去做呢?我正在浏览MSDN文档,我感到非常困惑。我是WPF和C#的新手,但我必须让这个工作。 –

+1

我更新了一个链接到示例的帖子 –

+0

是的,那是我正在看的那个。当我尝试与我的,它不起作用。它实际上是在抛出一些例外。 –

1

试试这个简单的一个:

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 
}