2012-11-15 49 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事件,而不是構造函數被調用。