Reputation: 17186
I've added an Adorner to my DateTimePicker control but it's not shown on top of the other controls. Why? How do I fix it?
My XAML currently goes like this:
<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>
The adorner itself is a separate class from the UserControl and added in the constructor:
public DateTimePicker()
{
InitializeComponent();
...
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(DateDisplay);
if (adornerLayer != null)
{
adornerLayer.Add(_upDownBtns = new TextBoxUpDownAdorner(DateDisplay));
_upDownBtns.Click += (textBox, direction) => { OnUpDown(direction); };
}
}
Upvotes: 3
Views: 5789
Reputation: 17186
The problem apparently occurs because the Adorners governed by the AdornerDecorator
are only guaranteed to appear on top of the controls inside the AdornerDecorator. It is necessary to wrap most of the contents of the window in an AdornerDecorator instead, but after doing this, AdornerLayer.GetAdornerLayer()
apprently can't see the AdornerDecorator under some circumstances and returns null.
The documentation claims "GetAdornerLayer walks up the visual tree, starting at the specified UIElement
, and returns the first adorner layer it finds." In reality, GetAdornerLayer
cannot find an AdornerDecorator
located outside of the UserControl
, at least not in .NET 3.5. I fixed the problem by doing exactly what GetAdornerLayer
claims to do itself:
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);
};
}
Finally, GetAdornerLayer
must be called from the Loaded
event instead of the constructor.
Upvotes: 1
Reputation: 71856
There's already an adorner layer in the default Window style, and that adorner layer sits above the content of the window.
So just remove the AdornerLayer from the UserControl and that should work.
Upvotes: 0