Collapsing XML nodes only works once

SyntaxEditor Web Languages Add-on for WPF Forum

Posted 5 months ago by Sascha Nitschke
Version: 13.2.0592
Avatar

Hello Actipro,

my application

  1. loads a new view incl. a new XML SyntaxEditor within the main window
  2. collapes XML elements onload (see code below)
  3. unloads the view and its viewmodel (i.a. view.DataContext = null;)
private static void CollapseRecursively(IOutliningNode node)
{
    node.IsCollapsed = true;

    foreach (var subnode in node)
    {
        CollapseRecursively(subnode);
    }
}
[Conditional("DEBUG")]
private void TEST_CollapseXmlNodes()
{
    SyntaxEditor editor = GetSyntaxEditor();
    editor.UpdateLayout(); // Without this call the "RootNode" property is always empty.
	
    XmlParseData parseData = (XmlParseData)editor.Document.ParseData;
    IAstNode astNode = parseData.Ast.Children.SingleOrDefault();
	
    IOutliningNode rootNode = editor.Document.OutliningManager.RootNode.SingleOrDefault();

    if (rootNode != null)
    {
        foreach (var node in rootNode)
        {
            CollapseRecursively(node);
        }
    }
}

When you open the view the first time, it works fine: The necessary elements are collapsed.
"astNode" and "RootNode" have exactly one child. Perfect!

The problem:
After that if you close and open it again nothing is collapsed.
"astNode" and "RootNode" are empty (see also: comment in code).

What can I do?

[Modified 5 months ago]

Comments (6)

Posted 5 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

It's hard to say what's happening here without debugging through the scenario.  Can you make a new simple sample project with the code needed to make this issue occur and send that to our support address?  Please reference this thread in your email and exclude the bin/obj folders from the .zip you send so it doesn't get spam blocked.  Then we can debug this scenario to see what is causing the problem and get back to you.  Thanks!


Actipro Software Support

Posted 5 months ago by Sascha Nitschke
Avatar

I will try to reduce my application. This may take a while. I hope to reproduce the issue.

Posted 5 months ago by Sascha Nitschke
Avatar

Hello Actipro,

after several tests I have found out that collapsing on the first time NOT always works. So when starting the outlining directly after loading the SyntaxEditor (or its document) it seems that it is still not ready.

I have changed the method by adding a short "sleep" and removing some test variables:

[Conditional("DEBUG")]
private void TEST_CollapseXmlNodes()
{
    Thread.Sleep(500);	// TODO: Remove/replace

    if (ViewModel.SelectedSyntaxEditor.Document.OutliningManager.RootNode.SingleOrDefault() is IOutliningNode rootNode)
    {
        foreach (IOutliningNode subNode in rootNode)
        {
            CollapseRecursively(subNode);
        }
    }
}

This seems to work but Thread.Sleep() it is ugly and not really consistent here. Is there a way to run TEST_CollapseXmlNodes() AFTER the SyntaxEditor initialization threads have completely finished?

Posted 5 months ago by Sascha Nitschke
Avatar

This is consistent

while (AmbientParseRequestDispatcherProvider.Dispatcher.IsBusy)
{
    Thread.Sleep(50);
}

but "active waiting" is still ugly ;)

Posted 5 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Sascha,

In the Web Languages Add-on, code outlining is driven by the AST nodes in parse data created by the XML parser.  The parser generally runs asynchronously in a worker thread.  Thus what might be happening here is that the parsing isn't completed yet when your code executes, and without the AST info in the parse data, no outlining nodes will be there yet to collapse.

What happens if you run your collapse logic in response to the SyntaxEditor.DocumentParseDataChanged event?


Actipro Software Support

Posted 5 months ago by Sascha Nitschke
Avatar

Hello Actipro,

thank you for the event name. Yes, RootNode is never null here. But without active waiting not all nodes will be collapsed. Furthermore AmbientParseRequestDispatcherProvider.Dispatcher.IsBusy is still true. My decision is a combination of the event and Thread.Sleep(). This seems to work. Thank you for your help :).

Regards
Sascha

The latest build of this product (v22.1.4) was released 26 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.