Skip to content

Instantly share code, notes, and snippets.

@CodingOctocat
Created March 27, 2025 11:08
Show Gist options
  • Save CodingOctocat/466ed70eaeb5915d1a23caf706abeb33 to your computer and use it in GitHub Desktop.
Save CodingOctocat/466ed70eaeb5915d1a23caf706abeb33 to your computer and use it in GitHub Desktop.
WPF/DashedBorder
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
/// <summary>
/// <see href="https://stackoverflow.com/a/72138376/4380178">How can I achieve a dashed or dotted border in WPF?</see>
/// </summary>
public class DashedBorder : Border
{
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()));
public static readonly DependencyProperty UseDashedBorderProperty =
DependencyProperty.Register(
nameof(UseDashedBorder),
typeof(bool),
typeof(DashedBorder),
new FrameworkPropertyMetadata(false, OnUseDashedBorderChanged));
private static DoubleCollection? _emptyDoubleCollection;
public Brush DashedBorderBrush
{
get => (Brush)GetValue(DashedBorderBrushProperty);
set => SetValue(DashedBorderBrushProperty, value);
}
public DoubleCollection StrokeDashArray
{
get => (DoubleCollection)GetValue(StrokeDashArrayProperty);
set => SetValue(StrokeDashArrayProperty, value);
}
public bool UseDashedBorder
{
get => (bool)GetValue(UseDashedBorderProperty);
set => SetValue(UseDashedBorderProperty, value);
}
private static DoubleCollection EmptyDoubleCollection()
{
if (_emptyDoubleCollection == null)
{
DoubleCollection doubleCollection = [];
doubleCollection.Freeze();
_emptyDoubleCollection = doubleCollection;
}
return _emptyDoubleCollection;
}
private static void OnUseDashedBorderChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var dashedBorder = (DashedBorder)target;
dashedBorder.UseDashedBorderChanged();
}
private VisualBrush CreateDashedBorderBrush()
{
var dashedBorderBrush = new VisualBrush();
var grid = new Grid();
var backgroundRectangle = GetBackgroundRectangle();
var dashedRectangle = GetDashedRectangle();
grid.Children.Add(backgroundRectangle);
grid.Children.Add(dashedRectangle);
dashedBorderBrush.Visual = grid;
return dashedBorderBrush;
}
private Rectangle GetBackgroundRectangle()
{
var rectangle = GetBoundRectangle();
rectangle.SetBinding(Rectangle.StrokeProperty, new Binding() { Source = this, Path = new PropertyPath(BackgroundProperty) });
return rectangle;
}
private Rectangle GetBoundRectangle()
{
var 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 GetDashedRectangle()
{
var 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 void UseDashedBorderChanged()
{
if (UseDashedBorder)
{
BorderBrush = CreateDashedBorderBrush();
}
else
{
ClearValue(BorderBrushProperty);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment