我是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);
}
非常简单。由于我的实际操作很长,我希望列表框能够像我每次更新一样更新 - 如何在每次添加时动态更新列表框?
答案 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));
}
}
}