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<string>
并将您的 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 (SDF) 数据库中的项目填充 WPF 列表框