AdornerLayer.GetAdornerLayer() return NULL for all

2020-07-22 19:40发布

问题:

I'm facing the fact that i cannot understand Well how AdornerLayer is added for UIElements.

I have such a situation:

I have a WPF Form which is built with 3 controls: A Grid on which are 1 Button and 1 TextBox.

In my System, when I click to open this Form, all 3 elements have AdornerLayer not null .

 var controls = _frameworkElementProvider.GetUIElements(Content);
 var controlsWithAddorner = new List<FrameworkElement>();

 foreach (var control in controls) {
    var adornerLayer = AdornerLayer.GetAdornerLayer(control);
    if (adornerLayer != null) {
       controlsWithAddorner.Add(control);
    }
 }   

The collection controlsWithAddorner contains all my 3 controls.

The method GetUIElements(FrameworkElement parent) returns an IEnumerable<FrameworkElement> in which are all controls within a Panel.

I have such a functionality: Refresh Form Designer. Which recreates the xaml for that Form.

After that Refresh is done, I check the list of controls for AdornerLayer. For all controls the AdornerLayer is null.

The problem is here, I cannot understand where AdornerLayer (s) are lost? Should I take care To add them forr each UIElement when I Refresh the Designer of the Form?

Please advice me with some suggestions.

Thank you!


EDIT: I'll show all the solution if other will encounter such problems :)

The mission is: When there is a SelectedControl in designer, keep it selected even a RefreshDesigner is done.

RefreshDesigner functionality recreates the xaml for the whole form.

// Refresh the Designer
private void RefreshDesigner() {    
    Content = _xamlProvider.ParseXaml(_xaml.ToString());

    //Here was the Problem. All visual child elements of the Content wa not updated after xaml recreation.
    //By including that call -> solved the problem
    Content.UpdateLayout();
}

Firstly: The xaml of the Form is Updated by using the ParseXaml() method from XamlProvider

// in XamlProvider class 
public Panel ParseXaml(string xaml) {
    var regex = new Regex("<Grid ");
    const int first = 1;
    xaml = Regex.Replace(xaml, @"xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""", string.Empty);
    xaml = Regex.Replace(xaml, @"xml:space=""preserve""", string.Empty);

    //...

    xaml = Regex.Replace(xaml, "<BindingGroup .*/>", string.Empty);

    var content = (Panel)XamlReader.Parse(xaml);
    return content;
}

Secondly: Content.UpdateLayout(); Ensures that all visual child elements of this element are properly updated for layout. MSDN Official source

After that, All elements have AdornelLayer not Null and I'm able to set the Adorner Border for preciosly selected control in designer.

回答1:

After the Form is Refreshed, call Content.UpdateLayout(); to Ensures that all visual child elements of the Content were properly updated for layout. MSDN official