我现在面临的问题是,我不太理解AdornerLayer是如何为UI元素添加的。
我的情况是这样的:
我有一个WPF表单,上面有3个控件:
一个网格(Grid),上面有1个按钮(Button)和1个文本框(TextBox)。
在我的系统中,当我点击打开这个表单时,这三个元素的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,也要保持其选定状态。
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();
}
首先:使用XamlProvider
的ParseXaml()
方法更新表单的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,并且我能够在设计师中为精确选择的控件设置装饰边框。
Content.UpdateLayout();
以确保Content的所有可视子元素已经正确更新布局。 - mihai