AdornerLayer.GetAdornerLayer()对于Panel中的所有控件返回NULL

3

我现在面临的问题是,我不太理解AdornerLayer是如何为UI元素添加的。

我的情况是这样的:

我有一个WPF表单,上面有3个控件: 一个网格(Grid),上面有1个按钮(Button)和1个文本框(TextBox)enter image description here

在我的系统中,当我点击打开这个表单时,这三个元素的AdornerLayer不为空

 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);
    }
 }   

集合controlsWithAddorner包含了我所有的3个控件。

方法GetUIElements(FrameworkElement parent)返回一个IEnumerable<FrameworkElement>,其中包含在Panel中的所有控件。

我有这样一个功能:刷新表单设计器。它重新创建了该表单的xaml。

在完成刷新之后,我检查AdornerLayer的控件列表。对于所有控件,AdornerLayer为null。

问题在于,我不知道AdornerLayer(s)去哪了?当我刷新表单的设计师时,我是否应该为每个UIElement添加它们?

请给我一些建议。

谢谢!


编辑: 如果其他人遇到此类问题,我将展示所有解决方案 :)

任务是:当设计器中有选定的控件时,即使进行RefreshDesigner,也要保持其选定状态。

enter image description here

RefreshDesigner功能重新创建整个表单的xaml。

// 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();
}

首先:使用XamlProviderParseXaml()方法更新表单的xaml。

// 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;
}

其次: Content.UpdateLayout(); 确保此元素的所有可视子元素已正确更新以进行布局。 MSDN官方来源 之后,所有元素都具有非空的AdornelLayer,并且我能够在设计师中为精确选择的控件设置装饰边框。

1
通常这应该可以工作。我假设一些框架元素被克隆或从 VisualTree 中分离了。你能直接尝试获取一个控件的 AdornerLayer 吗?例如,var adornerLayer = AdornerLayer.GetAdornerLayer(yourButton); 这样行得通吗? - SvenG
@SvenG,谢谢。 实际给出的代码可以正常处理面板中的所有控件,但我尝试获取具体控件的AdornerLayer,因为我想使用一个Adorner边框在设计器中视觉上显示“SelectedControl”,但它返回NULL。 我找到了问题所在。 在刷新表单后,我应该调用Content.UpdateLayout();以确保Content的所有可视子元素已经正确更新布局。 - mihai
请查看此处:https://dev59.com/LXA75IYBdhLWcg3w6Nlj - Vlad
1个回答

3
刷新表单后,调用Content.UpdateLayout();确保Content的所有可视子元素都已正确更新以适应布局。更多详情参见MSDN 官方文档

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接