绘制具有不同颜色端盖的WPF线

时间:2017-03-13 14:22:22

标签: c# wpf

WPF新手。我需要绘制一条线(在网格内部"单元格",如果这有所不同),其开始/结束上限与线本身颜色不同。似乎在线上获得上限很容易;让它成为一种不同的颜色并不是那么简单。

我查看了Line,PolyLine,Pen,Path,LineGeometry和EllipseGeometry对象。所有这些似乎都为我的问题提供了部分解决方案。 This文章似乎最接近解决方案,但代码示例不完整。

很高兴接受我的问题的任何建议或解决方案。

2 个答案:

答案 0 :(得分:0)

这是一个想法......使用线性渐变画笔

draw

答案 1 :(得分:0)

你可以自己动手。这是我找到并修改以满足我的需求的代码。 我添加了 CapStroke CapStrokeThickness 属性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace LineCaps
{

    public class CappedLine: FrameworkElement
    {        
        protected override void  OnRender(DrawingContext dc)
        {
            Point pos, tangent;
            double angleInRadians;
            double angleInDegrees;
            TransformGroup tg;
            Pen pen = new Pen(Stroke, StrokeThickness);
            dc.DrawGeometry(null, pen, LinePath);

            Pen capPen = new Pen(CapStroke, CapStrokeThickness);
            if (BeginCap != null)
            {
                LinePath.GetPointAtFractionLength(0.01d, out pos, out tangent);
                angleInRadians = Math.Atan2(tangent.Y, tangent.X) + Math.PI;
                angleInDegrees = angleInRadians * 180 / Math.PI + 180;
                tg = new TransformGroup();
                tg.Children.Add(new RotateTransform(angleInDegrees));
                LinePath.GetPointAtFractionLength(0.0d, out pos, out tangent);
                tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                dc.PushTransform(tg);
                dc.DrawGeometry(CapStroke, capPen, BeginCap);
                dc.Pop();
            }
            if (EndCap != null)
            {
                LinePath.GetPointAtFractionLength(0.99, out pos, out tangent);
                angleInRadians = Math.Atan2(tangent.Y, tangent.X) + Math.PI;
                angleInDegrees = angleInRadians * 180 / Math.PI;
                tg = new TransformGroup();
                tg.Children.Add(new RotateTransform(angleInDegrees));
                LinePath.GetPointAtFractionLength(1, out pos, out tangent);
                tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                dc.PushTransform(tg);
                dc.DrawGeometry(CapStroke, capPen, EndCap);
            }         
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            //TODO: Consider creating the Pen once when Stroke and StrokeThickness are set
            return LinePath.GetRenderBounds(new Pen(Stroke, StrokeThickness)).Size;
        }

        public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(typeof(CappedLine));
        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(typeof(CappedLine));
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static DependencyProperty CapStrokeProperty =
        DependencyProperty.Register(
            "CapStroke",
            typeof(Brush),
            typeof(CappedLine));
        public Brush CapStroke
        {
            get { return (Brush)GetValue(CapStrokeProperty); }
            set { SetValue(CapStrokeProperty, value); }
        }

        public static readonly DependencyProperty CapStrokeThicknessProperty =
        DependencyProperty.Register(
            "CapStrokeThickness",
            typeof(double),
            typeof(CappedLine));

        public double CapStrokeThickness
        {
            get { return (double)GetValue(CapStrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static readonly DependencyProperty LinePathProperty =
            DependencyProperty.Register("LinePath", typeof(PathGeometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                LinePathChangedCallback));
        static void LinePathChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnLinePathChanged((PathGeometry)args.NewValue);
            }
        }
        public PathGeometry LinePath
        {
            get { return (PathGeometry)GetValue(LinePathProperty); }
            set { SetValue(LinePathProperty, value); }
        }
        public virtual void OnLinePathChanged(PathGeometry value)
        {
        }

        public static readonly DependencyProperty BeginCapProperty =
            DependencyProperty.Register("BeginCap", typeof(Geometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                BeginCapChangedCallback));
        static void BeginCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnBeginCapChanged((Geometry)args.NewValue);
            }
        }
        public Geometry BeginCap
        {
            get { return (Geometry)GetValue(BeginCapProperty); }
            set { SetValue(BeginCapProperty, value); }
        }
        public virtual void OnBeginCapChanged(Geometry value)
        {
        }

        public static readonly DependencyProperty EndCapProperty =
            DependencyProperty.Register("EndCap", typeof(Geometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                EndCapChangedCallback));
        static void EndCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnEndCapChanged((Geometry)args.NewValue);
            }
        }
        public Geometry EndCap
        {
            get { return (Geometry)GetValue(EndCapProperty); }
            set { SetValue(EndCapProperty, value); }
        }
        public virtual void OnEndCapChanged(Geometry value)
        {
        }
    }
}

然后使用它:

<Window x:Class="LineCaps.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:loc="clr-namespace:LineCaps"
        Title="MainWindow">
    <Viewbox>
        <Canvas Height="350" Width="525">
            <loc:CappedLine BeginCap="M0,0 L6,-6 L6,6 z" EndCap="M0,-3 L0,3 L6,3 L6,-3 z" Stroke="Gold" StrokeThickness="1" CapStroke="Green" CapStrokeThickness="1" Canvas.Left="40" Canvas.Top="60">
                <loc:CappedLine.LinePath>
                    <PathGeometry Figures="M0,0 L120,120" />
                </loc:CappedLine.LinePath>
            </loc:CappedLine>

            <loc:CappedLine EndCap="M0,0 L6,-6 L6,6 z" Stroke="Blue" StrokeThickness="1" CapStroke="Red" CapStrokeThickness="1"  Canvas.Left="40" Canvas.Top="200" RenderTransformOrigin="1.5,0.5">
                <loc:CappedLine.BeginCap>
                    <EllipseGeometry Center="0,0" RadiusX="6" RadiusY="6" />
                </loc:CappedLine.BeginCap>
                <loc:CappedLine.LinePath>
                    <PathGeometry Figures="M0,0 C1,1 10.5,75.5 48.5,66.5 86.5,57.5 53.5,3.5000146 105.5,16.500091 157.5,29.500166 164.5,87.500505 164.5,87.500505" />
                </loc:CappedLine.LinePath>
                <loc:CappedLine.RenderTransform>
                    <RotateTransform Angle="0" />
                </loc:CappedLine.RenderTransform>
            </loc:CappedLine>

        </Canvas>
    </Viewbox>
</Window>