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

时间:2009-12-10 23:26:36

标签: c# wpf listbox refresh

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

    <ListBox Height="87" Margin="12,0,12,10" Name="lbxProgress" VerticalAlignment="Bottom">
        <ListBox.BindingGroup>
            <BindingGroup Name="{x:Null}" NotifyOnValidationError="False" />
        </ListBox.BindingGroup>
    </ListBox>

,点击处理程序就像

private void btn_Click(object sender, RoutedEventArgs e)  
{  
  List<String> lstrFiles= new List<String>(System.IO.Directory.GetFiles   ("C:\\temp", "*.tmp");  

  foreach(string strFile in lstrFiles)  
    lbxProgress.Items.Add(strFile);  
}  

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

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:4)

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

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

答案 2 :(得分:2)

要获得完整的答案,以下是生成的代码段,减去一些错误处理代码:

namespace Whatever  
{  
  public partial class MyWindow : Window  
  {  
    public delegate void CopyDelegate();  
    private string m_strSourceDir;  // Source directory - set elsewhere.  
    private List<string> 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<string> 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<String>(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<string>();  
      lbxProgress.ItemsSource= m_osstrProgress;  
      lbxProgress.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new CopyDelegate(CopyFiles));  
    }  
  }  
}  
相关问题