加载文件时,显示动画gif弹出窗口

时间:2014-05-28 12:54:57

标签: c# winforms

我的程序的目标是将目录加载到我的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);
        }

    }

}

2 个答案:

答案 0 :(得分:0)

这取决于您的BuildTree()方法是否可以在后台线程上执行。 因为您正在传递对TreeView控件属性的引用,我假设该代码必须在UI线程上执行。 在这种情况下,我只能建议你调用Application.DoEvents();从BuildTree()方法中,例如在循环中。

此外,如果您要进行任何长期调用以获取BuildTree()方法中的数据,您应该在后台线程上进行这些操作并以任何方便的方式与UI同步。

<强> [编辑] 我快速浏览了一下BuildTree()方法。我认为在这种情况下,最好的方法是:

  1. 声明其他数据结构,以保存所有已填充的数据以填充TreeView。
  2. 在背景上填写所有数据(您可以使用BackgroundWorker) here is a good question突出显示如何从BackgroundWorker获取结果
  3. 准备好所有数据后,创建所有节点并将其添加到TreeView。这也需要一些时间,但必须在UI线程上完成。 为了保持UI响应,您可以在循环中调用Application.DoEvents(),在该循环中您将向树中添加新节点
  4. 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
}));