Как нарисовать 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, и это должно работать.

Другие вопросы по тегам