In my WPF application, I would like to style reactangle for dag and drop the file. The appearance of this box should look like this.

It is possible to achieve this result in XAML?
So far I have managed to achieve just this.

The problem is in the corners I. The appearance of the corners should be like connection line of two dashes. For example, bottom left corner - "L" with possibility to resize the reactangle.
Here is my current code, which a created with help of this answer:
How can I achieve a dashed or dotted border in WPF?
<Rectangle
Fill="LightGray"
AllowDrop="True"
Stroke="#FF000000"
StrokeThickness="2"
StrokeDashArray="5 4"
SnapsToDevicePixels="True"
MinHeight="200"
MinWidth="200"
/>
To get these nice, L-shaped corners in WPF you'll have to draw the horizontal and vertical borders separately since the StrokeDashArray will not (always) be the same for both.
Your requirements for the StrokeDashArray are:
To get the precise length needed to draw a line like that you have to calculate the number of lines (+1) and spaces in your dashes line, e.g. like this:
private IEnumerable<double> GetDashArray(double length)
{
double useableLength = length - StrokeDashLine;
int lines = (int)Math.Round(useableLength/(StrokeDashLine + StrokeDashSpace));
useableLength -= lines*StrokeDashLine;
double actualSpacing = useableLength/lines;
yield return StrokeDashLine / StrokeThickness;
yield return actualSpacing / StrokeThickness;
}
Wrap that up in a custom control and you will get something like this:

<local:NiceCornersControl Fill="LightGray" Stroke="Black"
StrokeThickness="2" StrokeDashLine="5" StrokeDashSpace="5">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
Text="Drop files here"/>
</local:NiceCornersControl>
A couple of things you should be aware of:
StrokeThickness / 2DashStyle will scale with your StrokeThicknessFull code for the control:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace InsertNamespaceHere
{
public class NiceCornersControl : ContentControl
{
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
"Stroke", typeof(Brush), typeof(NiceCornersControl), new PropertyMetadata(default(Brush), OnVisualPropertyChanged));
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness", typeof(double), typeof(NiceCornersControl), new PropertyMetadata(default(double), OnVisualPropertyChanged));
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
public static readonly DependencyProperty StrokeDashLineProperty = DependencyProperty.Register(
"StrokeDashLine", typeof(double), typeof(NiceCornersControl), new PropertyMetadata(default(double), OnVisualPropertyChanged));
public double StrokeDashLine
{
get { return (double)GetValue(StrokeDashLineProperty); }
set { SetValue(StrokeDashLineProperty, value); }
}
public static readonly DependencyProperty StrokeDashSpaceProperty = DependencyProperty.Register(
"StrokeDashSpace", typeof(double), typeof(NiceCornersControl), new PropertyMetadata(default(double), OnVisualPropertyChanged));
public double StrokeDashSpace
{
get { return (double)GetValue(StrokeDashSpaceProperty); }
set { SetValue(StrokeDashSpaceProperty, value); }
}
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
"Fill", typeof(Brush), typeof(NiceCornersControl), new PropertyMetadata(default(Brush), OnVisualPropertyChanged));
public Brush Fill
{
get { return (Brush)GetValue(FillProperty); }
set { SetValue(FillProperty, value); }
}
private static void OnVisualPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((NiceCornersControl)d).InvalidateVisual();
}
public NiceCornersControl()
{
SnapsToDevicePixels = true;
UseLayoutRounding = true;
}
protected override void OnRender(DrawingContext drawingContext)
{
double w = ActualWidth;
double h = ActualHeight;
double x = StrokeThickness / 2.0;
Pen horizontalPen = GetPen(ActualWidth - 2.0 * x);
Pen verticalPen = GetPen(ActualHeight - 2.0 * x);
drawingContext.DrawRectangle(Fill, null, new Rect(new Point(0, 0), new Size(w, h)));
drawingContext.DrawLine(horizontalPen, new Point(x, x), new Point(w - x, x));
drawingContext.DrawLine(horizontalPen, new Point(x, h - x), new Point(w - x, h - x));
drawingContext.DrawLine(verticalPen, new Point(x, x), new Point(x, h - x));
drawingContext.DrawLine(verticalPen, new Point(w - x, x), new Point(w - x, h - x));
}
private Pen GetPen(double length)
{
IEnumerable<double> dashArray = GetDashArray(length);
return new Pen(Stroke, StrokeThickness)
{
DashStyle = new DashStyle(dashArray, 0),
EndLineCap = PenLineCap.Square,
StartLineCap = PenLineCap.Square,
DashCap = PenLineCap.Flat
};
}
private IEnumerable<double> GetDashArray(double length)
{
double useableLength = length - StrokeDashLine;
int lines = (int)Math.Round(useableLength / (StrokeDashLine + StrokeDashSpace));
useableLength -= lines * StrokeDashLine;
double actualSpacing = useableLength / lines;
yield return StrokeDashLine / StrokeThickness;
yield return actualSpacing / StrokeThickness;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With