2011-10-25 49 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

相关问题