2012-11-15 107 views
2

我在我的DateTimePicker control中添加了一个装饰,但它并未显示在其他控件的顶部。为什么?我如何解决它?如何绘制WPF装饰物?

My adorner

我的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> 

装饰器本身是从用户控件一个单独的类,并在构造函数中添加:

public DateTimePicker() 
{ 
    InitializeComponent(); 
    ... 

    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(DateDisplay); 
    if (adornerLayer != null) 
    { 
     adornerLayer.Add(_upDownBtns = new TextBoxUpDownAdorner(DateDisplay)); 
     _upDownBtns.Click += (textBox, direction) => { OnUpDown(direction); }; 
    } 
} 

回答

0

有已经装饰器图层默认为Window样式,并且该装饰图层位于窗口内容的上方。

所以,只需从UserControl中删除AdornerLayer,它应该可以工作。

+0

'AdornerDecorator'存在,因为没有它,'GetAdornerLayer'返回null。 – Qwertie

+0

啊,在控件的激活事件中,而不是构造函数中进行装饰器设置。在GetAdornerLayer可以获得Windows AdornerLayer之前,控件需要在屏幕上。 –

+0

什么事件? UserControl上没有激活事件。我尝试过'Loaded',但是'GetAdornerLayer'在那个事件中仍然返回null。 – Qwertie

1

这个问题很明显是因为受到AdornerDecorator治理的Adorners只能保证出现在AdornerDecorator内的控件之上。有必要将窗口的大部分内容封装在AdornerDecorator中,但是在这样做后,AdornerLayer.GetAdornerLayer()在某些情况下无法看到AdornerDecorator并返回null。

该文档声明“GetAdornerLayer从指定的UIElement开始走向可视化树,并返回找到的第一个装饰层。”实际上,GetAdornerLayer找不到位于UserControl以外的AdornerDecorator,至少不在.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事件,而不是构造函数被调用。