C# TreeView sometimes refuse to paint itself after

2019-06-12 16:22发布

I use a TreeView to display some informations in two levels :

  • A
  • B
    • 1
  • D
    • 1
    • 2
  • ...

Sometimes, the informations stored in the treeview differs with the one displayed. It seems that it's because Paint() is not called after Invalidates().

I already tried answer from this question : C# Treeview doesn't refresh after moving nodes, without success.

Tree (re)Creation code :

using System.Windows.Forms.TreeNode;
using System.Windows.Forms.TreeView;
[...]
private void createTree()
{
    [...]// Creation code
    // Check update of the treeview
    foreach (TreeNode n in viewDataTreeView.Nodes) 
    {
        Console.WriteLine(n.Name);
        foreach (TreeNode child in n.Nodes)
        {
            Console.WriteLine("   " + child.Name);
        }
    }
    Console.WriteLine("done");
    this.Invalidate(true);
}

Which always output the correct tree that I have in the treeview. And sometimes, newly added node are not displayed on the screen.

Working case:

enter image description here

callstack: enter image description here

Functions of working callstack :

private void toolStripDeleteTemplateButton_Click(object sender, EventArgs e)
{
    //Some confirmation stuff
    [...]
    // Delete the template file
    GraphTemplateNode node = this.viewDataTreeView.SelectedNode as GraphTemplateNode;
    File.Delete(node.GetTemplateFilePath());

    createTree();
}

Not working case:

enter image description here

callstack: enter image description here

See the Test 4 is missing.

Functions of unworking callstack :

//LineGraphUIControl.cs
private void saveTemplateToolStripButton_Click(object sender, EventArgs e)
{
    base.SaveGraphTemplate(lineGraphControl1.Graph);
}

//GraphUIControl.cs
public void SaveGraphTemplate(Graph graph)
{
    //Getting file name
    [...]
    //Creating template
    ViewDataSubControl.AddNewUserTemplate(tmplt);
}

// ViewDataSubControl.cs
public void AddNewUserTemplate(GraphTemplate tmplt)
{
    //Some string calculations
    [...]
    tmplt.SaveTemplate(fullName);
    createTree();
}

I tried to use the method Refresh(), Update() and BeginUpdate() & EndUpdate() with no luck. The event Invalidated is always fired, but I can't get Paint() to be called everytime. If I force call with InvokePaint() the TreeView is not updated either.

What can I do to make it works ?

1条回答
叼着烟拽天下
2楼-- · 2019-06-12 16:57

That issue is unusual, and I suspect that it is something wrong in the logic that renders the TreeView. You wrote in a comment that the code is long, you did not create it and you don't want to copy/paste it.

I understand this.

In general, there are many reasons why it could happen:

  • It might be a missing EndUpdate at some point. Check the code that runs when you delete and re-add a node.

  • Node display customization can be troublesome. Check any code that could have an impact on node rendering (the DrawNode event for example)

  • Check exception handlers. An exception could happens and break a code flow. Remove empty catch sections if it applies.

  • It might be a misuse of a trick like this one that disable Redraws on demand to speed up the display. In this last case, a missing ResumeDrawing could lock it the same way.

Unfortunately it is very hard to guess what is wrong without the whole code... So the best I can do to help is to give some advices to check what it is going on:

  • At first, comment every BeginUpdate, EndUpdate, SuspendDrawing, ResumeDrawing together, and check what happens.

  • If the bug is still here, have a code that populates the TreeView as simple as possible by commenting what is not related to it, Disable events that are used to customize the node display like the DrawNode event (if it applies)

...until it works as expected.

  • Then, uncomment pieces of codes to re-enable existing features, one by one, until you bump on the issue or notice what is wrong by looking at the code. You will isolate the bug this way.

Hope it helps at least a bit.

查看更多
登录 后发表回答