【问题标题】:Using VisualBrush as OpacityMask使用 VisualBrush 作为 OpacityMask
【发布时间】:2011-06-26 06:50:57
【问题描述】:

我想将OpacityMask 设置为控件,但我需要动态构建该掩码。 以下是它的外观:


整个(红色)矩形的宽度和高度是动态的,基于父控件的宽度和高度。但我需要在左上角和右上角放置两个小矩形(静态宽度和高度),如图所示。那么我该如何实现呢?

我试过这段代码,但它不起作用:(什么都不显示)

<Border BorderBrush="#80FFFFFF" BorderThickness="1" CornerRadius="5">
    <Border.OpacityMask>
        <VisualBrush>
            <VisualBrush.Visual>
                <DockPanel>
                    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Height="2">
                        <Border Background="Transparent" Width="12" VerticalAlignment="Stretch" HorizontalAlignment="Left" />
                        <Border Background="Black" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
                        <Border Background="Transparent" Width="12" VerticalAlignment="Stretch" HorizontalAlignment="Right" />
                    </StackPanel>

                    <Border Background="Black" />
                </DockPanel>
            </VisualBrush.Visual>
        </VisualBrush>
    </Border.OpacityMask>
</Border>

以这种方式使用VisualBrush(作为OpacityMask)是否有效?

【问题讨论】:

    标签: c# .net wpf xaml visualbrush


    【解决方案1】:

    如果我正确理解您的问题,您希望图像中的那些黑色方块是透明的吗?

    更新:在此处上传示例项目:http://www.mediafire.com/?5tfkd1cxwfq0rct

    我认为问题在于VisualBrush 内的Panel 不会拉伸。您可以通过将您使用的任何Panel 的宽度和高度绑定到Border 的ActualWidth 和ActualHeight 来获得所需的效果

    <Border Name="border" BorderBrush="Red" BorderThickness="1" CornerRadius="5">
        <Border.OpacityMask>
            <VisualBrush>
                <VisualBrush.Visual>
                    <Grid Width="{Binding ElementName=border, Path=ActualWidth}"
                          Height="{Binding ElementName=border, Path=ActualHeight}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="20"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="20"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Rectangle Fill="Transparent" Grid.Column="0"/>
                        <Rectangle Fill="Black" Grid.Column="1"/>
                        <Rectangle Fill="Transparent" Grid.Column="2"/>
                        <Rectangle Fill="Black" Grid.Row="1" Grid.ColumnSpan="3"/>
                    </Grid>
                </VisualBrush.Visual>
            </VisualBrush>
        </Border.OpacityMask>
        <Grid>
            <TextBlock Text="Testing OpacityMask with a rather long string................." Grid.ZIndex="3"/>
            <Rectangle Fill="Green"/>
        </Grid>
    </Border>
    

    再次更新
    Border 的 Decorator Child 的 DropShadowEffect 似乎在 Verticaly 和 Horizo​​ntaly 上推动了 Border 的 OpacityMask。更糟糕的是它似乎是堆叠的,所以在你的例子中,当你有三个嵌套的Decorators 的三个 DropShadowEffects 时,BlurRadius 的总和是 45 (20+15+10) 所以 OpacityMask 被推送一个值45(至少看起来这是怎么回事,但有点难说..)。您可以尝试通过增加 ColumnDefinition Widths 和 RowDefinition Heights 来弥补这一点,但我认为很难找到动态解决方案。

    解决您的问题的更好方法可能是使用Border.Clip,但这也不容易。

    Point1:  0, 2
    Point2: 12, 2
    Point3: 12, 0
    Point4: Width of Border - 12, 0
    Point5: Width of Border - 12, 2
    Point5: Width of Border, 2
    Point6: Width of Border, Height of Border
    Point7: 0, Height of Border
    

    更新 3
    想出了一个不需要这么多绑定的更好的解决方案。创建一个派生自 Border 的自定义类并覆盖 GetLayoutClip。这适用于 Designer 和 Runtime。为了增加ClippedBorder 的灵活性,您可以引入一些依赖属性来代替硬编码的 2 和 12。这里的新示例应用程序:http://www.mediafire.com/?9i13rrqpbmzdbvs

    public class ClippedBorder : Border
    {
        protected override Geometry GetLayoutClip(Size layoutSlotSize)
        {
            PathGeometry pathGeometry = new PathGeometry();
            pathGeometry.Figures = new PathFigureCollection();
    
            //Point1:  0, 2
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = new Point(0, 2);
    
            //Point2: 12, 2
            LineSegment lineSegment1 = new LineSegment();
            lineSegment1.Point = new Point(12, 2);
    
            //Point3: 12, 0
            LineSegment lineSegment2 = new LineSegment();
            lineSegment2.Point = new Point(12, 0);
    
            //Point4: Width of Border - 12, 0
            LineSegment lineSegment3 = new LineSegment();
            lineSegment3.Point = new Point(this.ActualWidth-12, 0);
    
            //Point5: Width of Border - 12, 2
            LineSegment lineSegment4 = new LineSegment();
            lineSegment4.Point = new Point(this.ActualWidth-12, 2);
    
            //Point5: Width of Border, 2
            LineSegment lineSegment5 = new LineSegment();
            lineSegment5.Point = new Point(this.ActualWidth, 2);
    
            //Point6: Width of Border, Height of Border
            LineSegment lineSegment6 = new LineSegment();
            lineSegment6.Point = new Point(this.ActualWidth, this.ActualHeight);
    
            //Point7: 0, Height of Border 
            LineSegment lineSegment7 = new LineSegment();
            lineSegment7.Point = new Point(0, this.ActualHeight);
    
            pathFigure.Segments.Add(lineSegment1);
            pathFigure.Segments.Add(lineSegment2);
            pathFigure.Segments.Add(lineSegment3);
            pathFigure.Segments.Add(lineSegment4);
            pathFigure.Segments.Add(lineSegment5);
            pathFigure.Segments.Add(lineSegment6);
            pathFigure.Segments.Add(lineSegment7);
    
            pathGeometry.Figures.Add(pathFigure);
    
            return pathGeometry;
        }
    }
    

    【讨论】:

    • 是的,黑色方块应该是透明的。我试过你的代码,但它不起作用 - 它显示了一切。我试图增加行/列的宽度/高度,它仍然显示内容。
    • @Paja:好的,我上传了我的示例项目,它似乎正在运行。试试看,让我知道可能有什么不同
    • @Paja:刚刚检查,您是否为Border 设置了Name="border"
    • 是的,你是对的,它有效。但我不能让它在我的程序中工作。 :-( 当边框没有任何附加内容时它可以工作。一旦我插入带有一些元素的网格,OpacityMask 将被忽略。不应该对子元素也有 OpacityMask 效果吗?
    • @Paja:我无法重现您的问题,您是对的,它也应该适用于 Child 元素。我插入了一个带有一些孩子的Grid,它仍在工作。请参阅我更新的示例。代码您发布了一些重现您的问题的示例代码?
    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 2019-05-04
    • 2015-05-07
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多