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

Posted

技术标签:

【中文标题】WPF 列表框动态填充 - 如何让它刷新?【英文标题】:WPF listbox dynamically populated - how to get it to refresh? 【发布时间】:2010-12-25 11:38:02 【问题描述】:

我是 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);  
  

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

【问题讨论】:

总结其他答案:始终使用数据绑定(并且更喜欢可观察的集合);永远不要在代码中手动将项目添加到容器中。 总结上面的评论:嗯?这有什么变化吗?将更新和刷新这样简单的操作混淆起来有什么意义? 【参考方案1】:

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

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

【讨论】:

你是说没有ListBox更新功能吗?如果我想控制何时进行更新,我不能使用 ObservableCollection。【参考方案2】:

创建一个ObservableCollection&lt;string&gt; 并将您的 ListBox.ItemsSource 设置为该集合。因为集合是可观察的,所以 ListBox 将随着其内容的变化而更新。

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

【讨论】:

我的操作是复制一个文件,这可能涉及创建一个目录,所以我阻塞了 UI 线程。我利用了 Dispatcher.BeginInvoke 功能。【参考方案3】:

为了获得完整的答案,这里是生成的代码 sn-p,减去一些错误处理代码:

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

【讨论】:

以上是关于WPF 列表框动态填充 - 如何让它刷新?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQL 值动态填充列表框

使用 SQL (SDF) 数据库中的项目填充 WPF 列表框

使用数组 C# WPF 中的项目填充列表框

C#WPF如何在由数据模板中的对象列表组成的列表框中设置项目[重复]

使用工具提示 WPF 在数据网格中填充组合框

如何从模型中获取唯一的选项列表以填充选择框