2017-02-20 10 views
2

В моем приложении WPF я хотел бы создать regangle для dag и удалить файл. Внешний вид этого окна должен выглядеть так.WPF-ответная граница с углом от соединительной линии двух штрихов

What i want

можно достичь этого результата в XAML?

До сих пор мне удалось достичь именно этого.

What I currently have

Проблема заключается в углах I. Появление углов должно быть как линии соединения двух черточек. Например, нижний левый угол - «L» с возможностью изменения размера реактора.

Вот мой текущий код, который сотворенное с помощью этого ответа:
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" 
     /> 
+0

Ну, вы можете * нарисовать ее самостоятельно, перезаписав метод OnRender настраиваемого элемента управления. –

ответ

2

Чтобы получить эти хорошие, L-образные углы в WPF вы будете рисовать горизонтальные и вертикальные границы отдельно, так как StrokeDashArray не будет (всегда) одинаковым для обоих.

Ваши требования к StrokeDashArray являются:

  • Каждая строка должна начинаться и заканчиваться полным тире
  • Длина штрихов должна остаться такой же
  • избыток/недостающее расстояние должно быть заполнено растягивание пробела между штрихами

Чтобы получить точную длину, необходимую для рисования линии, вам необходимо вычислить количество строк (+1) и пробелов в строке штриховки, например. как это:

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, что в пользовательский элемент управления, и вы получите что-то вроде этого:

Dashed Rectangle with L-shaped corners

<local:NiceCornersControl Fill="LightGray" Stroke="Black" 
    StrokeThickness="2" StrokeDashLine="5" StrokeDashSpace="5"> 
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" 
     Text="Drop files here"/> 
</local:NiceCornersControl> 

Несколько вещей, которые вы должны знать о:

  • Чтобы ваша линия была «внутри» прямоугольника, вам необходимо их смещать на StrokeThickness/2
  • DashStyle масштабируется с StrokeThickness
  • Это, вероятно, будут выглядеть странно для полупрозрачных тактных цветов

Полный код для управления:

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; 
     } 
    } 
} 
+0

Хорошо выглядите. Как я могу использовать ваш компонент с прямоугольником? – Vrabec0853

+1

@ Vrabec0853 Вы использовали бы его ** вместо ** элемента управления Rectangle' (или напишите 'ControlTemplate', который его использует, или замените' Rectangle' вместо 'Control' /' ContentControl' и т. Д.). В качестве альтернативы вы можете написать «MultiValueConverter», который принимает ширину и высоту прямоугольника и преобразует его в смехотворно длинный StrokeDashArray, который содержит * каждый отдельный штрих *, необходимый для достижения этого внешнего вида. –

0

Это не ответ, но предложение. На самом деле, я не уверен, что это возможно в простой форме (возможно, вы могли бы рассчитать StrokeDashArray, получив ширину и высоту элемента управления).Тем не менее, вы можете использовать анимацию:

<Grid Margin="3"> 
    <Rectangle Name="Rect" 
    Fill="LightGray" 
    AllowDrop="True" 
    Stroke="#FF000000" 
    StrokeThickness="2" 
    StrokeDashArray="5 4" 
    SnapsToDevicePixels="True" 
    MinHeight="200" 
    MinWidth="200" 
    > 
     <Rectangle.Triggers> 
      <EventTrigger RoutedEvent="Window.Loaded"> 
       <BeginStoryboard> 
        <Storyboard > 
         <DoubleAnimation To="100" Duration="0:0:10" RepeatBehavior="Forever" By="1" 
       Storyboard.TargetProperty="StrokeDashOffset" Storyboard.TargetName="Rect"/> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger> 
     </Rectangle.Triggers> 
    </Rectangle> 
</Grid> 

 Смежные вопросы

  • Нет связанных вопросов^_^