我的程序的目标是将目录加载到我的treeview节点,这需要10秒(因为目录驻留在远程PC中)。在此期间,我将添加一个等待的弹出图像。我复制了这篇文章的答案:How can i show an image while my application is loading 我的代码,如:
private void treeView2_AfterSelect(object sender, TreeViewEventArgs e)
{
Form f = new Form();
f.Size = new Size(20, 25);
Image im = Image.FromFile(@"C:\Documents and Settings\JiangC\Documenti\Immagini\loader.gif");
f.FormBorderStyle = FormBorderStyle.None;
f.MinimizeBox = false;
f.MaximizeBox = false;
f.AutoSize = true;
PictureBox pb = new PictureBox();
//pb.Dock = DockStyle.Fill;
pb.SizeMode = PictureBoxSizeMode.AutoSize;
pb.Image = im;
pb.Location = new Point(50, 50);
f.Controls.Add(pb);
f.Show();
// Application.DoEvents();
BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
f.Close();
}
我想要做的是在加载过程中(当Buildtree()方法实现时)将显示带有picturebox pb的表单f,加载后它们就会消失。
第一个问题是" pb.Dock = DockStyle.Fill;"
如果我取消注释,则在加载过程中不会显示此表单f(但我可以在屏幕底部看到它的最小化窗口)。只有当我从这条线上取下时,表格f才能显示出来。
第二个问题是" f.Show();"当显示表格f时,图片框pb根本没有显示(只是一个空洞)。如果我将其修改为" f.ShowDialog();",则可以显示带有图片的表单f。
然而,这里出现了第三个问题,即形式f将始终存在,我的函数" BuildTree();"根本没有实施!
第四个问题是,如果我添加行" Application.DoEvents();",它工作得很好,在加载期间将显示带有图片框的表单f,并且在加载之后f将消失,但f中的图片是gif,在这种情况下,gif根本没有动画!
所以有人可以帮我解决问题吗?
这是我的BuildTree函数代码:
private void BuildTree(DirectoryInfo[] directoryInfo, TreeNodeCollection addInMe, TreeNode clicked)
{
for (int i = 0; i < directoryInfo.Length; i++)
{
var files = directoryInfo[i].GetFiles();
int length = files.Length;
clicked.Nodes.Add(directoryInfo[i].Name);
List<TreeNode> dateNode = new List<TreeNode>();
string[] allDates = new string[length];
try
{
for (int j = 0; j < length; j++)
{
allDates[j] = files[j].Name.Substring(11, 6);
}
}
catch (Exception e)
{ }
string[] date = allDates.Distinct().ToArray();
for (int k = 0; k < date.Length; k++) //From here to the end
{
// is my code loading file
dateNode.Add(clicked.Nodes.Add(date[i]));
for (int j = 0; j < length; j++)
{
// curNode.Nodes.Add(file.FullName, file.Name);
if (files[j].Name.Substring(11, 6) == date[i])
{
dateNode[i].Nodes.Add(files[j].FullName, files[j].Name);
}
}
}
foreach (DirectoryInfo subdir in directoryInfo[i].GetDirectories())
{
BuildTree(subdir, clicked.Nodes);
}
}
}
答案 0 :(得分:0)
这取决于您的BuildTree()方法是否可以在后台线程上执行。 因为您正在传递对TreeView控件属性的引用,我假设该代码必须在UI线程上执行。 在这种情况下,我只能建议你调用Application.DoEvents();从BuildTree()方法中,例如在循环中。
此外,如果您要进行任何长期调用以获取BuildTree()方法中的数据,您应该在后台线程上进行这些操作并以任何方便的方式与UI同步。
<强> [编辑] 强> 我快速浏览了一下BuildTree()方法。我认为在这种情况下,最好的方法是:
treeView2_AfterSelect()中的代码如下所示:
//...
f.Show();
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (ss, ee) =>
{
ee.Result = PrepareData(directory); // prepare all data required to build the Tree
}
bw.RunWorkerCompleted += (ss, ee) =>
{
BuildTreeByData(ee.Result, addInMe, clicked);
f.Close();
}
bw.RunWorkerAsync();
答案 1 :(得分:0)
在调用f.Show():
之前,将此行添加到代码中f.Activated += (s, e) => BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
// it's f.Shown for Windows Forms, Activated is for WPF
它为您的f表单的OnShow事件订阅一个匿名事件处理程序。在这个处理程序中,您只需调用您的方法。
如果它不起作用,你将不得不在这里替换对BuildTree的调用BackgroundWorker call,因为你的BuildTree方法可能会访问UI控件,这是一个很大的禁忌。调用此代码而不是f.ShowDialog:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (ss, ee) =>
{
f.ShowDialog(this);
BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
}
bw.RunWorkerCompleted += (ss, ee) => f.Close();
bw.RunWorkerAsync();
并在BuildTree中更改对控件的每次访问和修改,如下所示:
this.Invoke((MethodInvoker) (() =>
{
// access you control here
}));