Как нарисовать WPF Adorners поверх всего остального?
Я добавил Adorner в свой элемент управления DateTimePicker, но он не отображается поверх других элементов управления. Зачем? Как мне это исправить?
Мой XAML в настоящее время выглядит так:
<UserControl x:Class="IntelliMap.WPF.DateTimePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpftc="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
mc:Ignorable="d">
...
<AdornerDecorator>
<Grid>
...
<TextBox x:Name="DateDisplay"
HorizontalAlignment="Stretch" ...>
</TextBox>
...
</Grid>
</AdornerDecorator>
</UserControl>
Сам Adorner является отдельным классом от UserControl и добавлен в конструктор:
public DateTimePicker()
{
InitializeComponent();
...
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(DateDisplay);
if (adornerLayer != null)
{
adornerLayer.Add(_upDownBtns = new TextBoxUpDownAdorner(DateDisplay));
_upDownBtns.Click += (textBox, direction) => { OnUpDown(direction); };
}
}
2 ответа
Проблема, очевидно, возникает из-за того, что AdornerDecorator
гарантированно отображаются только сверху элементов управления внутри AdornerDecorator. Вместо этого необходимо обернуть большую часть содержимого окна в AdornerDecorator, но после этого AdornerLayer.GetAdornerLayer()
При некоторых обстоятельствах AdornerDecorator не может видеть Adorner и возвращает значение NULL.
Документация утверждает, что "GetAdornerLayer поднимается по визуальному дереву, начиная с указанного UIElement
и возвращает первый найденный рекламный слой."На самом деле, GetAdornerLayer
не могу найти AdornerDecorator
расположен за пределами UserControl
По крайней мере, не в.NET 3.5. Я исправил проблему, делая именно то, что GetAdornerLayer
претензии делать самому:
static AdornerLayer GetAdornerLayer(FrameworkElement subject)
{
AdornerLayer layer = null;
do {
if ((layer = AdornerLayer.GetAdornerLayer(subject)) != null)
break;
} while ((subject = subject.Parent as FrameworkElement) != null);
return layer;
}
public DateTimePicker()
{
InitializeComponent();
...
this.Loaded += (s, e) =>
{
// not null anymore!
AdornerLayer adLayer = GetAdornerLayer(DateDisplay);
};
}
В заключение, GetAdornerLayer
должен быть вызван из Loaded
событие вместо конструктора.
В стандартном стиле Window уже есть слой adorner, и этот слой adorner находится над содержимым окна.
Так что просто удалите AdornerLayer из UserControl, и это должно работать.