2013-09-11 176 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 
}