programing

WPF에서 점선 또는 점선 테두리를 설정하려면 어떻게 해야 합니까?

yellowcard 2023. 4. 25. 22:14
반응형

WPF에서 점선 또는 점선 테두리를 설정하려면 어떻게 해야 합니까?

저 있어요.ListViewItem적용한다는 것을 의미합니다.Style도트 그레이 라인을 맨 아래쪽에 붙이고 싶습니다.Border.

WPF에서 이 작업을 수행하려면 어떻게 해야 합니까?단색 브러시밖에 안 보여요.

이 기능은 응용 프로그램에서 매우 잘 작동하여 직사각형을 조작하지 않고 실제 테두리를 사용할 수 있습니다.

<Border BorderThickness="1,0,1,1">
   <Border.BorderBrush>
      <DrawingBrush Viewport="0,0,8,8" ViewportUnits="Absolute" TileMode="Tile">
         <DrawingBrush.Drawing>
            <DrawingGroup>
               <GeometryDrawing Brush="Black">
                  <GeometryDrawing.Geometry>
                     <GeometryGroup>
                        <RectangleGeometry Rect="0,0,50,50" />
                        <RectangleGeometry Rect="50,50,50,50" />
                     </GeometryGroup>
                  </GeometryDrawing.Geometry>
               </GeometryDrawing>
            </DrawingGroup>
         </DrawingBrush.Drawing>
      </DrawingBrush>
   </Border.BorderBrush>

   <TextBlock Text="Content Goes Here!" Margin="5"/>
</Border>

뷰포트는 라인의 대시 크기를 결정합니다.이 경우 8픽셀 대시를 생성합니다.Viewport="0,0,4,4"는 4개의 대시를 제공합니다.

아래 코드와 같이 직사각형을 사용하여 점선 또는 대시선을 만들 수 있습니다.

<Rectangle Stroke="#FF000000" Height="1" StrokeThickness="1" StrokeDashArray="4 4"
                                                       SnapsToDevicePixels="True"/>

이 작업을 시작하고 시나리오에 따라 목록 보기를 사용자 지정합니다.

파티에는 조금 늦었지만, 다음과 같은 해결책이 효과가 있었습니다.이 솔루션은 다른 두 솔루션보다 약간 더 단순하고 좋습니다.

<Border BorderThickness="1">
  <Border.BorderBrush>
    <VisualBrush>
      <VisualBrush.Visual>
        <Rectangle StrokeDashArray="4 2" Stroke="Gray" StrokeThickness="1"
                  Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
                  Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
      </VisualBrush.Visual>
    </VisualBrush>
  </Border.BorderBrush>

  <TextBlock Text="Whatever" />
</Border>

Xaml입니다.

<Grid>
<Grid.RowDefinitions><RowDefinition Height="auto"/></Grid.RowDefinitions>
<Grid.ColumnDefinitions><ColumnDefinition Width="auto"/></Grid.ColumnDefinitions>
<Rectangle RadiusX="9" RadiusY="9" Fill="White" Stroke="Black" StrokeDashArray="1,2"/>
<TextBlock Padding = "4,2" Text="Whatever"/>
</Grid>

우리 팀은 최근에 이것을 요구조건으로 받았고 우리는 그것을 맞춤형 컨트롤을 만들어서 해결했습니다.DashedBorder확장됩니다.Border파선 테두리 피쳐를 추가합니다.

3개의 새 종속성 속성이 있습니다.

  • UseDashedBorder(부엉) (부엉) (부울어요.
  • DashedBorderBrush(브러쉬)입니다.
  • StrokeDashArray(이중 수집)입니다.

이렇게 사용할 수 있습니다.

<controls:DashedBorder UseDashedBorder="True"
                       DashedBorderBrush="#878787"
                       StrokeDashArray="2 1"
                       Background="#EBEBEB"                               
                       BorderThickness="3"
                       CornerRadius="10 10 10 10">
    <TextBlock Text="Dashed Border"
               Margin="6 2 6 2"/>
</controls:DashedBorder>

그리고 이런 결과를 낳습니다.

언제UseDashedBorder로 설정됩니다.true생성될 것입니다.VisualBrush두 개의 직사각형으로 설정하고 다음과 같이 설정합니다.BorderBrush(그렇기 때문에 실제 색상에 대한 추가 속성이 필요합니다.BorderBrush첫 번째 방법은 대시 생성이고 두 번째 방법은 빈칸을 채우는 것입니다.Background국경에서요

이 지도는 다음과 같습니다.Rectangle속성을 에 추가합니다.DashedBorder이와 같은 특성입니다.

  • StrokeDashArray=> 입니다.StrokeDashArray
  • Stroke=> 입니다.DashedBorderBrush
  • StrokeThickness=> 입니다.BorderThickness.Left
  • RadiusX=> 입니다.CornerRadius.TopLeft
  • RadiusY=> 입니다.CornerRadius.TopLeft
  • Width=> 입니다.ActualWidth
  • Height=> 입니다.ActualHeight

DashedBorder.cs

    public class DashedBorder : Border
    {
        private static DoubleCollection? emptyDoubleCollection;
        private static DoubleCollection EmptyDoubleCollection()
        {
            if (emptyDoubleCollection == null)
            {
                DoubleCollection doubleCollection = new DoubleCollection();
                doubleCollection.Freeze();
                emptyDoubleCollection = doubleCollection;
            }
            return emptyDoubleCollection;
        }

        public static readonly DependencyProperty UseDashedBorderProperty =
          DependencyProperty.Register(nameof(UseDashedBorder),
                                      typeof(bool),
                                      typeof(DashedBorder),
                                      new FrameworkPropertyMetadata(false, OnUseDashedBorderChanged));

        public static readonly DependencyProperty DashedBorderBrushProperty =
          DependencyProperty.Register(nameof(DashedBorderBrush),
                                      typeof(Brush),
                                      typeof(DashedBorder),
                                      new FrameworkPropertyMetadata(null));

        public static readonly DependencyProperty StrokeDashArrayProperty =
          DependencyProperty.Register(nameof(StrokeDashArray),
                                      typeof(DoubleCollection),
                                      typeof(DashedBorder),
                                      new FrameworkPropertyMetadata(EmptyDoubleCollection()));

        private static void OnUseDashedBorderChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            DashedBorder dashedBorder = (DashedBorder)target;
            dashedBorder.UseDashedBorderChanged();
        }

        private Rectangle GetBoundRectangle()
        {
            Rectangle rectangle = new Rectangle();

            rectangle.SetBinding(Rectangle.StrokeThicknessProperty, new Binding() { Source = this, Path = new PropertyPath("BorderThickness.Left") });
            rectangle.SetBinding(Rectangle.RadiusXProperty, new Binding() { Source = this, Path = new PropertyPath("CornerRadius.TopLeft") });
            rectangle.SetBinding(Rectangle.RadiusYProperty, new Binding() { Source = this, Path = new PropertyPath("CornerRadius.TopLeft") });
            rectangle.SetBinding(Rectangle.WidthProperty, new Binding() { Source = this, Path = new PropertyPath(ActualWidthProperty) });
            rectangle.SetBinding(Rectangle.HeightProperty, new Binding() { Source = this, Path = new PropertyPath(ActualHeightProperty) });

            return rectangle;
        }

        private Rectangle GetBackgroundRectangle()
        {
            Rectangle rectangle = GetBoundRectangle();
            rectangle.SetBinding(Rectangle.StrokeProperty, new Binding() { Source = this, Path = new PropertyPath(BackgroundProperty) });
            return rectangle;
        }

        private Rectangle GetDashedRectangle()
        {
            Rectangle rectangle = GetBoundRectangle();
            rectangle.SetBinding(Rectangle.StrokeDashArrayProperty, new Binding() { Source = this, Path = new PropertyPath(StrokeDashArrayProperty) });
            rectangle.SetBinding(Rectangle.StrokeProperty, new Binding() { Source = this, Path = new PropertyPath(DashedBorderBrushProperty) });
            Panel.SetZIndex(rectangle, 2);
            return rectangle;
        }

        private VisualBrush CreateDashedBorderBrush()
        {
            VisualBrush dashedBorderBrush = new VisualBrush();
            Grid grid = new Grid();
            Rectangle backgroundRectangle = GetBackgroundRectangle();
            Rectangle dashedRectangle = GetDashedRectangle();
            grid.Children.Add(backgroundRectangle);
            grid.Children.Add(dashedRectangle);
            dashedBorderBrush.Visual = grid;
            return dashedBorderBrush;
        }

        private void UseDashedBorderChanged()
        {
            if (UseDashedBorder)
            {
                BorderBrush = CreateDashedBorderBrush();
            }
            else
            {
                ClearValue(BorderBrushProperty);
            }
        }

        public bool UseDashedBorder
        {
            get { return (bool)GetValue(UseDashedBorderProperty); }
            set { SetValue(UseDashedBorderProperty, value); }
        }

        public Brush DashedBorderBrush
        {
            get { return (Brush)GetValue(DashedBorderBrushProperty); }
            set { SetValue(DashedBorderBrushProperty, value); }
        }

        public DoubleCollection StrokeDashArray
        {
            get { return (DoubleCollection)GetValue(StrokeDashArrayProperty); }
            set { SetValue(StrokeDashArrayProperty, value); }
        }
    }

사용자 컨트롤에 대해 작업하는 중입니다.행진하는 개미들의 국경 스토리보드를 시도해 봤어요직사각형과 텍스트가 있는 기본 그리드는 상호 작용이 없으므로 올바르게 작동합니다.그리드 내부에 버튼을 넣으려고 하면 직사각형이나 버튼 중 하나가 표시되지만 둘 다 표시되지 않습니다.

다른 게시물에서 왔습니다.고급 XAML 애니메이션 효과입니다. 맥박, 행진 개미, 회전이요 경고합니다.

VisualBrush용 dotNet 솔루션을 사용하여 안에 있는 버튼을 사용하여 사각형을 테두리로 이동했습니다.완벽하게 작동했어요

<UserControl.Resources>
    <ResourceDictionary>
        <Style TargetType="{x:Type TextBlock}" x:Key="LOC_DG_Cell_Mid" BasedOn="{StaticResource DG_TextBlock_Mid}" >
            <Setter Property="Margin" Value="5 0"/>
        </Style>
        <Storyboard x:Key="MarchingAnts">
            <DoubleAnimation BeginTime="00:00:00"
                Storyboard.TargetName="AlertBox"                                
                Storyboard.TargetProperty="StrokeThickness"
                To="4"
                Duration="0:0:0.25" />
            <!-- If you want to run counter-clockwise, just swap the 'From' and 'To' values. -->
            <DoubleAnimation BeginTime="00:00:00" RepeatBehavior="Forever" Storyboard.TargetName="AlertBox" Storyboard.TargetProperty="StrokeDashOffset" 
                            Duration="0:3:0" From="1000" To="0"/>
        </Storyboard>
    </ResourceDictionary>

</UserControl.Resources>
<UserControl.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource MarchingAnts}"/>
    </EventTrigger>
</UserControl.Triggers>

<Grid>
    <Border BorderThickness="1">
        <Border.BorderBrush>
            <VisualBrush>
                <VisualBrush.Visual>
                    <Rectangle x:Name="AlertBox" Stroke="Red" StrokeDashOffset="2" StrokeDashArray="5" Margin="5"
                      Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
                      Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
                </VisualBrush.Visual>
            </VisualBrush>
        </Border.BorderBrush>

        <Button x:Name="FinishedButton" Padding="0 5" Margin="0" Style="{StaticResource IconButton}" >
            <StackPanel Orientation="Horizontal" >
                <Label Style="{StaticResource ButtonLabel}" Content="Processing has Finished" />
            </StackPanel>
        </Button>
    </Border>
</Grid>

픽셀의 완벽한 점선을 찾는 경우입니다.

각 라인의 끝에는 그림자/흐림이 없습니다.

public static class DashBrushFactory
    {
        public static Brush CreateBrush(double dpiScale, SolidColorBrush solidColorBrush)
        {
            const double dashLength = 4;
            const double dashSpace = 4;

            double dashLengthPixelSnapped = SnapToPixel(dashLength, dpiScale);
            double dashSpacePixelSnapped = SnapToPixel(dashSpace, dpiScale);

            ImageBrush imageBrush = new ImageBrush();
            DrawingImage drawingImage = new DrawingImage();
            GeometryDrawing geometryDrawing = new GeometryDrawing();
            GeometryGroup geometryGroup = new GeometryGroup();
            RectangleGeometry rectangleGeometry1 = new RectangleGeometry();
            RectangleGeometry rectangleGeometry2 = new RectangleGeometry();

            rectangleGeometry1.Rect = new Rect(0, 0, dashLengthPixelSnapped, dashLengthPixelSnapped);
            rectangleGeometry2.Rect = new Rect(dashLengthPixelSnapped, dashLengthPixelSnapped, dashSpacePixelSnapped, dashSpacePixelSnapped);

            rectangleGeometry1.Freeze();
            rectangleGeometry2.Freeze();

            geometryGroup.Children.Add(rectangleGeometry1);
            geometryGroup.Children.Add(rectangleGeometry2);
            geometryGroup.Freeze();

            geometryDrawing.Brush = solidColorBrush;
            geometryDrawing.Geometry = geometryGroup;
            geometryDrawing.Freeze();

            drawingImage.Drawing = geometryDrawing;
            drawingImage.Freeze();
            imageBrush.TileMode = TileMode.Tile;
            imageBrush.ViewportUnits = BrushMappingMode.Absolute;
            imageBrush.Viewport = new Rect(0, 0, dashLengthPixelSnapped * 2, dashSpacePixelSnapped * 2);
            imageBrush.ImageSource = drawingImage;
            imageBrush.Freeze();

            return imageBrush;
        }

        private static double SnapToPixel(double value, double dpiScale)
        {
            double newValue;

            // If DPI == 1, don't use DPI-aware rounding.
            if (DoubleUtil.AreClose(dpiScale, 1.0) == false)
            {
                newValue = Math.Round(value * dpiScale) / dpiScale;
                // If rounding produces a value unacceptable to layout (NaN, Infinity or MaxValue), use the original value.
                if (DoubleUtil.IsNaN(newValue) ||
                    Double.IsInfinity(newValue) ||
                    DoubleUtil.AreClose(newValue, Double.MaxValue))
                {
                    newValue = value;
                }
            }
            else
            {
                newValue = Math.Round(value);
            }

            return newValue;
        }
    }

https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Internal/DoubleUtil.cs를 참조하십시오.

언급URL : https://stackoverflow.com/questions/6195395/how-can-i-achieve-a-dashed-or-dotted-border-in-wpf 입니다.

반응형