Использование VisualBrush в качестве OpacityMask - PullRequest
2 голосов
/ 13 февраля 2011

Я хочу установить OpacityMask для элемента управления, но мне нужно построить эту маску динамически.Вот как это должно выглядеть:

http://i54.tinypic.com/350lc3a.png
Ширина и высота всего (красного) прямоугольника является динамической, в зависимости от ширины и высоты родительского элемента управления.Но мне нужно разместить два маленьких прямоугольника (статическая ширина и высота) в верхнем левом и правом верхнем углу, как показано на рисунке.Итак, как я могу это сделать?

Я пробовал этот код, но он не работает: (ничего не отображается)

<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)?

1 Ответ

3 голосов
/ 13 февраля 2011

Если я правильно понимаю ваш вопрос, вы хотите, чтобы эти черные квадраты на вашем изображении были прозрачными?

Обновление : загруженный образец проекта здесь: http://www.mediafire.com/?5tfkd1cxwfq0rct

Iдумаю, проблема в том, что Panel внутри VisualBrush не растянется.Вы можете получить желаемый эффект, привязав ширину и высоту любого Panel, который вы используете к ActualWidth и ActualHeight Border

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

Обновите снова
DropShadowEffect для декоратора Дочерний элемент Border, кажется, выдвигает маску Opacity для Border как по вертикали, так и по горизонтали.И что еще хуже, кажется, что он складывается, поэтому в вашем примере, когда у вас есть три DropShadowEffects для трех вложенных Decorators, сумма BlurRadius равна 45 (20 + 15 + 10), поэтому OpacityMask выдвигается значением45 (по крайней мере, похоже, что это происходит, но это немного трудно сказать ..).Вы можете попытаться компенсировать это, увеличив ширину ColumnDefinition и высоту RowDefinition, но я думаю, что будет трудно найти динамическое решение.

Лучшим подходом к вашей проблеме может быть использование 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.Это работает как в дизайнере, так и во время выполнения.Чтобы увеличить гибкость 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;
    }
}
...