WPF列表框动态填充 – 如何让它刷新?

我是WPF的新手,所以我觉得这很简单。 我有一个带有列表框和按钮的表单。 在按钮的单击处理程序中,我迭代地执行一些生成字符串的操作,我想将它放入列表框中。 列表框的xaml就像

     

和点击处理程序是一样的

 private void btn_Click(object sender, RoutedEventArgs e) { List lstrFiles= new List(System.IO.Directory.GetFiles ("C:\\temp", "*.tmp"); foreach(string strFile in lstrFiles) lbxProgress.Items.Add(strFile); } 

很简单。 由于我的实际操作很长,我希望列表框能够像我每次更新一样进行更新 – 如何在每次添加时动态更新框?

创建一个ObservableCollection并将ListBox.ItemsSource设置为该集合。 由于集合是可观察的,因此ListBox将随着其内容的更改而更新。

但是,如果您的实际操作阻止了UI线程,则可能会阻止WPF在操作完成之前更新UI(因为WPF数据绑定基础结构无法运行)。 因此,您可能需要在后台线程上运行冗长的操作。 在这种情况下,由于WPF交叉线程限制,您将无法从后台线程更新ObservableCollection(您可以更新属性,但不能更新集合)。 要解决此问题,请使用Dispatcher.BeginInvoke()更新UI线程上的集合,同时继续在后台线程上执行操作。

不要使用List <>,使用ObservableCollection <> 。 与普通List不同,Observable集合会在添加或删除项目时触发事件,这将导致任何正在侦听的对象正常运行 – 例如列表框刷新以反映新的/已删除的项目。

如果需要排序,分组,过滤,请考虑使用CollectionView 。

要获得完整的答案,以下是生成的代码段,减去一些error handling代码:

 namespace Whatever { public partial class MyWindow : Window { public delegate void CopyDelegate(); private string m_strSourceDir; // Source directory - set elsewhere. private List m_lstrFiles; // To hold the find result. private string m_strTargetDir; // Destination directory - set elsewhere. private int m_iFileIndex; // To keep track of where we are in the list. private ObservableCollection m_osstrProgress; // To attach to the listbox. private void CopyFiles() { if(m_iFileIndex == m_lstrFiles.Count) { System.Windows.MessageBox.Show("Copy Complete"); return; } string strSource= m_lstrFiles[m_iFileIndex]; // Full path. string strTarget= m_strTargetDir + strSource.Substring(strSource.LastIndexOf('\\')); string strProgress= "Copied \"" + strSource + "\" to \"" + strTarget + '\"'; try { System.IO.File.Copy(strFile, strTarget, true); } catch(System.Exception exSys) { strProgress = "Error copying \"" + strSource + "\" to \"" + strTarget + "\" - " + exSys.Message; } m_osstrProgress.Add(strProgress); ++m_iFileIndex; lbxProgress.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle, new CopyDelegate(CopyFiles)); } private void btnCopy_Click(object sender, RoutedEventArgs e) { m_lstrFiles= new List(System.IO.Directory.GetFiles(m_strSourceDir, "*.exe")); if (0 == m_lstrFiles.Count) { System.Windows.MessageBox.Show("No .exe files found in " + m_strSourceDir); return; } if(!System.IO.Directory.Exists(m_strTargetDir)) { try { System.IO.Directory.CreateDirectory(m_strTargetDir); } catch(System.Exception exSys) { System.Windows.MessageBox.Show("Unable to create " + m_strTargetDir + ": " + exSys.Message); return; } } m_iFileIndex= 0; m_osstrProgress= new ObservableCollection(); lbxProgress.ItemsSource= m_osstrProgress; lbxProgress.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new CopyDelegate(CopyFiles)); } } }