开发者

Using ProgressBar while populating a huge TreeView

I am populating a treeview with a lot of data, and usually it takes a while for program to give back the control to user (I guess it is just too much process on the treeview side). So I decided to give a progress bar to show things are going fine to user.

In this treeview I select a folder and all xml files in that folder will be added to this folder and the treeview looks like this:

+ FOLDER NAME 1
|__xml file name 1
|__xml file name 2
+FOLDER NAME 2
|__xml file name 1
|__xml file name 2

So problem is, my progressbar will be completed actually much faster than the treeview itself, I think it is the time for progam that is making the treeview visible that takes the must time. How can I do this?

This is my code for browing a folder and passing it to a function to populate treeview (Sorry taht is too long but I though it gonna make it more clear) As you see I want that 50% of progress bar to be filled in this part and other 50 while adding nodes to treeview:

        private void toolStripBrowseDirectory_Click(object sender, EventArgs e)
    {
        //Reset progressbar
        toolStripProgressBar.Value = 0;

        folderBrowser.ShowNewFolderButton = false;
        DialogResult result = folderBrowser.ShowDialog();

        int countAllfiles = 0;
        int countGoodFiles = 0;

        if (result == DialogResult.OK)
        {
            toolStripProgressBar.Value = 0;

            string selectedFolder = folderBrowser.SelectedPath;
            string[] files = Directory.GetFiles(selectedFolder, "*.xml", SearchOption.AllDirectories);
            List<string> goodFiles = new List<string>();

            toolStripProgressBar.Maximum = files.Length;

            countAllfiles = files.GetLength(0);

            //Folder name
            FileInfo folderInfo = new FileInfo(selectedFolder);
            string folderName = folderInfo.Name;

            if (countAllfiles != 0)
            {
                foreach (string file in files)
                {
                    //file name
                    FileInfo fileInfo = new FileInfo(file);
                    string fileName = fileInfo.Name;

                    try
                    {
                 开发者_Python百科       XmlDocument checkFileType = new XmlDocument();
                        checkFileType.Load(file);

                        if (checkFileType.SelectSingleNode("//Document/@Type").Value == "Test Results")
                        {
                            countGoodFiles++;
                            goodFiles.Add(file);
                        }
                    }
                    catch (Exception a)
                    {
                        StartForm.setDebug("Comparison Mode", a.Message, 21, "Can not read Selected XML file '" + fileName + "'", "Check file for compatibilyty", "File was excluded from list");
                    }

                    this.toolStripProgressBar.PerformStep();
                }

                if (countGoodFiles == 0)
                {
                    MessageBox.Show("There are no compatible XML files (exported from ZTR files) in '" + folderName + "'", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    StartForm.setDebug("Comparison Mode", "N/A", 20, "There are no compatible XML files (exported from ZTR files) in '" + folderName + "'", "Select a folder that contains compatible files!", "No file has been added to Select File Tree");
                    toolStripProgressBar.Value = 100;
                }
                else if (countGoodFiles > 0)
                {
                    this.Cursor = Cursors.WaitCursor;

                    AddFilesToTree(folderName, goodFiles.ToArray());

                    this.Cursor = Cursors.Default;
                }
            }
            else
            {
                MessageBox.Show("There are no XML files in '" + folderName + "'", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);                    
            }
        }           
    }

And this is for poulating the treeview

        private void AddFilesToTree(string folder, string[] files)
    {
        //Define folder node
        TreeNode folderNode = new TreeNode();
        folderNode.Text = folder;
        folderNode.Name = "folder";
        folderNode.Tag = folder;

        treeViewBrowsedFiles.Nodes.Add(folderNode);

        //Define file node
        foreach (string file in files)
        {
            try
            {
            //To check if the file is a valid test result (converted to XML from ZTR files)
            XmlDocument checkFileType = new XmlDocument();
            checkFileType.Load(file);

                LoadZTRCmp xml = new LoadZTRCmp(file);

                TreeNode fileNode = new TreeNode();
                fileNode.Text = xml.FileInfo("BatchNumber");
                fileNode.Name = "file";
                fileNode.Tag = file;

                folderNode.Nodes.Add(fileNode);

                this.toolStripProgressBar.PerformStep();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        folderNode.Toggle();
    }

So how to do this right way?

Update: ** SOLVED ** I found the problem, I had to do this line before using function to add nodes to treeview!!!

                        toolStripProgressBar.Maximum += countGoodFiles;

                    AddFilesToTree(folderName, goodFiles.ToArray());

fixed MAX value for progress bar Still progressbar finishes (maxed out) before TreeView starts to load...


       int progressSteps = (files.Length / 100)/2;

That's quite mysterious but I certainly don't understand the logic. The code is hard to read, you should break it up and use more helper methods. Try this instead:

        toolStripProgressBar.Maximum = files.Length;


You can skip the progress bar if you just call Application.DoEvents() every so often, it'll show the TreeView expanding with the nodes and should be relevant enough to the user to know how much longer they have to wait.


Maybe use the progress bar mode of marquee, which just moves back and forth across the progress bar, and then hide the progress bar when the tree is done loading? That way you'd still get the visibility of the application is doing some work, and the user could know to wait?

progressBar1.Style = ProgressBarStyle.Marquee;


Check the value toolStripProgressBar.Maximum . Is it equal to the ProgressBar's Value when your process completes?

If your ProgressBar's Step property is 1 it should be equal to the number of steps you want to display on your ProgressBar. It's possible toolStripProgressBar.Maximum is set too high and so it never reaches the end before your process completes.


A better approach is probably to populate the branches of the tree on a need basis; so when your user opens a new branch, just get the sub-branches. Populating an entire tree in one go on start up is wasteful because the chances are that your user is only interested in a small part of the tree and does not want to wait for the entire thing to load just so that they can view the small part of the tree in which they are interested.


Take a look at the BackgroundWorker. It allows you to populate your treeview from a separate tread, making your user interface a lot more responsive. It also supports reporting progress, so if you still want to display a progress bar it is perfectly possible.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://www.codeproject.com/KB/cpp/BackgroundWorker_Threads.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜