2011-10-25 48 views
2

有沒有辦法獲得控件的形狀並將其轉換爲Geometry對象?以幾何形狀獲取控件的形狀

我有以下情況:在WPF應用程序中,彈出窗口將顯示。這個彈出窗口不是窗戶,它是一個控件,可以看到。應用程序的其餘部分會變暗,因爲應用程序上方有灰色層。

現在的問題是,這個灰色層也在彈出窗口本身之上,這是由應用程序的設計加上被點擊和打開的元素引起的,彈出窗口也不應該被圖層隱藏。我決定將裁剪幾何圖形附加到灰色圖層上,這很好,但我必須檢測我不想自己隱藏的所有表單和路徑。

所以回到我的問題:有沒有辦法獲得控件的形狀並將其轉換爲Geometry對象?例如。我找到了獲得控件的VisualBrush的方法,但也無法將其轉換 - 或者只是看不到它是如何實現的。

+1

您是否試圖創建一個彈出窗口,以便灰色層不覆蓋它?如果是這樣,您可以通過使用Z順序來控制組件的顯示順序: http://blogs.msdn.com/b/wpfsdk/archive/2006/06/13/controlling-zorder-using-the- zindex-property.aspx – stuartmclark

+1

我會用Adorner/AdornerLayer或Popup控件。這兩個元素都旨在顯示其他控件之上的信息,並且應該覆蓋您需要在視覺內容上方顯示一個Popup而不需要修剪任何內容。 請參閱 http://msdn.microsoft.com/en-us/library/ms749018.aspx 和 http://msdn.microsoft.com/en-us/library/ms747117.aspx – SvenG

+0

你們兩個都是對的,對於彈出窗口來說,使用Z-Index或控件已經符合我的需要會容易得多。我會嘗試使用其中一種可能性。但是,源代碼控制呢?被點擊的按鈕也不應該被彈出式覆蓋圖覆蓋。 – MatthiasG

回答

2

你可以這樣做: 從可視化樹中刪除按鈕並將其放置在裝飾器上。 裝飾者關閉後再次將其附加到原始父級。 我認爲這比修剪任何幾何圖形更靈活(例如,您可以在裝飾器上放置像usercontrols這樣的複雜內容)

以下示例使用Panel作爲按鈕的容器。

XAML中(窗口):

<Grid Margin="50" x:Name="myGrid" Background="LightBlue"> 
<Button x:Name="myButton" Width="80" Height="30" Click="myButton_Click">Show popup</Button> 

代碼背後: 私人FrameworkElementAdorner _adorner;私人面板__ __ __ __ __ __ __ __ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

private void myButton_Click(object sender, RoutedEventArgs e) 
{ 
    if (_adorner == null) 
    { 
    _adorner = new FrameworkElementAdorner(myGrid); 
    } 

    // remove the button from the parent panel and attach it to the adorner 
    // otherwise remove from adorner and attach to original parent again 
    if (_adorner.IsVisible) 
    { 
    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(myGrid); 
    adornerLayer.Remove(_adorner); 

    Panel parent = VisualTreeHelper.GetParent(myButton) as Panel; 
    if (parent != null) 
    { 
     parent.Children.Remove(myButton); 
    } 
    _originalParent.Children.Add(myButton); 
    } 
    else 
    { 
    _originalParent = VisualTreeHelper.GetParent(myButton) as Panel; 
    if (_originalParent != null) 
    { 
     _originalParent.Children.Remove(myButton); 
    } 

    // Create the Adorner with the original button in it 
    _adorner.Child = CreateAdornerContent(myButton); 

    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(myGrid); 
    adornerLayer.Add(_adorner); 
    } 
} 

/// <summary> 
/// Creates some dummy content for the adorner 
/// </summary> 
private FrameworkElement CreateAdornerContent(Button myButton) 
{ 
    Grid g = new Grid(); 
    g.Background = new SolidColorBrush(Colors.Yellow); 

    TextBlock tb = new TextBlock(); 
    tb.Text = "I am the Adorner"; 

    g.Children.Add(tb); 
    g.Children.Add(myButton); 
    return g; 
} 

在這裏,簡單的裝飾器剛剛顯示FrameworkElement的: 類FrameworkElementAdorner:裝飾器 { 私人FrameworkElement的_child;

public FrameworkElementAdorner(UIElement adornedElement) 
    : base(adornedElement) 
{ 
} 

protected override int VisualChildrenCount 
{ 
    get 
    { 
    return 1; 
    } 
} 

protected override Visual GetVisualChild(int index) 
{ 
    if (index != 0) throw new ArgumentOutOfRangeException(); 
    return _child; 
} 

public FrameworkElement Child 
{ 
    get 
    { 
    return _child; 
    } 
    set 
    { 
    if (_child != null) 
    { 
     RemoveVisualChild(_child); 
    } 
    _child = value; 
    if (_child != null) 
    { 
     AddVisualChild(_child); 
    } 
    } 
} 

protected override Size ArrangeOverride(Size finalSize) 
{ 
    _child.Arrange(new Rect(new Point(0, 0), finalSize)); 
    return new Size(_child.ActualWidth, _child.ActualHeight); 
} 

}

我也可以,如果你喜歡上載滿SLN。這在某種程度上可能嗎?

+0

+1爲您的答案,因爲它肯定會工作,並將是一個簡單的解決方案。不幸的是,我們無法修改視覺樹,因爲我們使用的是框架,並且對我們的客戶有嚴格的規範,而這是不允許的。我將不得不爲底層控件使用裁剪方法。只有彈出窗口本身可以通過將它們放在ZIndex較高的圖層中而不通過裁剪來顯示,但不能修改位於較深層上的控件。 – MatthiasG

+0

太壞了:(祝你好運找到理想的解決方案,然後...... – SvenG

+0

標記爲答案,因爲你做得很好,這不完全是我一直在尋找,但可以幫助其他人。 – MatthiasG

相關問題