2017-06-05 35 views
1

在最近的c#wpf應用程序中,我使用了oxyplot進行趨勢分析。這是一個在體積數據上具有高性能的好工具。我從LiveChart移動到Oxyplot。如何根據軸範圍實現截面背景? TargetEffectOxyPlot:如何根據軸範圍添加背景

我已經嘗試修改ThreeColorLineSeries,現在我可以根據設置喜和下限渲染線。但對於背景,它不起作用。

using System.Collections.Generic; 

/// <summary> 
/// Represents a two-color line series. 
/// </summary> 
public class FourColorLineSeries : LineSeries 
{ 
    /// <summary> 
    /// The default low color. 
    /// </summary> 
    private OxyColor defaultColorLoPre; 

    /// <summary> 
    /// The default low color. 
    /// </summary> 
    private OxyColor defaultColorLo; 

    /// <summary> 
    /// The default hi color. 
    /// </summary> 
    private OxyColor defaultColorLoLo; 

    /// <summary> 
    /// The default low color. 
    /// </summary> 
    private OxyColor defaultColorHiPre; 

    /// <summary> 
    /// The default low color. 
    /// </summary> 
    private OxyColor defaultColorHi; 

    /// <summary> 
    /// The default hi color. 
    /// </summary> 
    private OxyColor defaultColorHiHi; 

    /// <summary> 
    /// Initializes a new instance of the <see cref = "FourColorLineSeries" /> class. 
    /// </summary> 
    public FourColorLineSeries() 
    { 
     this.LimitHiPre = 1.0; 
     this.ColorHiPre = OxyColors.Green; 
     this.LineStyleHiPre = LineStyle.Solid; 

     this.LimitHi = 2.0; 
     this.ColorHi = OxyColors.Yellow; 
     this.LineStyleHi = LineStyle.Solid; 

     this.LimitHiHi = 5.0; 
     this.ColorHiHi = OxyColors.Red; 
     this.LineStyleHiHi = LineStyle.Solid; 

     this.LimitLoPre = -1.0; 
     this.ColorLoPre = OxyColors.Green; 
     this.LineStyleLoPre = LineStyle.Solid; 

     this.LimitLo = -2.0; 
     this.ColorLo = OxyColors.Yellow; 
     this.LineStyleLo = LineStyle.Solid; 

     this.LimitLoLo = -5.0; 
     this.ColorLoLo = OxyColors.Red; 
     this.LineStyleLoLo = LineStyle.Solid; 
    } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is below the limit. 
    /// </summary> 
    public OxyColor ColorLoPre { get; set; } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is below the limit. 
    /// </summary> 
    public OxyColor ColorLo { get; set; } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is above the limit. 
    /// </summary> 
    public OxyColor ColorLoLo { get; set; } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is below the limit. 
    /// </summary> 
    public OxyColor ColorHiPre { get; set; } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is below the limit. 
    /// </summary> 
    public OxyColor ColorHi { get; set; } 

    /// <summary> 
    /// Gets or sets the color for the part of the line that is above the limit. 
    /// </summary> 
    public OxyColor ColorHiHi { get; set; } 

    /// <summary> 
    /// Gets the actual low pre color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorLoPre 
    { 
     get { return this.ColorLoPre.GetActualColor(this.defaultColorLoPre); } 
    } 

    /// <summary> 
    /// Gets the actual low color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorLo 
    { 
     get { return this.ColorLo.GetActualColor(this.defaultColorLo); } 
    } 

    /// <summary> 
    /// Gets the actual low low color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorLoLo 
    { 
     get { return this.ColorLoLo.GetActualColor(this.defaultColorLoLo); } 
    } 

    /// <summary> 
    /// Gets the actual hi pre color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorHiPre 
    { 
     get { return this.ColorHiPre.GetActualColor(this.defaultColorHiPre); } 
    } 

    /// <summary> 
    /// Gets the actual hi color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorHi 
    { 
     get { return this.ColorHi.GetActualColor(this.defaultColorHi); } 
    } 

    /// <summary> 
    /// Gets the actual low color. 
    /// </summary> 
    /// <value>The actual color.</value> 
    public OxyColor ActualColorHiHi 
    { 
     get { return this.ColorHiHi.GetActualColor(this.defaultColorHiHi); } 
    } 

    /// <summary> 
    /// Gets or sets the high limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorHi. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitLoPre { get; set; } 

    /// <summary> 
    /// Gets or sets the low limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorLo. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitLo { get; set; } 

    /// <summary> 
    /// Gets or sets the pre limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorPre. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitLoLo { get; set; } 

    /// <summary> 
    /// Gets or sets the high limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorHi. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitHiPre { get; set; } 

    /// <summary> 
    /// Gets or sets the low limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorLo. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitHi { get; set; } 

    /// <summary> 
    /// Gets or sets the pre limit. 
    /// </summary> 
    /// <remarks>The parts of the line that is below this limit will be rendered with ColorPre. 
    /// The parts of the line that is above the limit will be rendered with Color.</remarks> 
    public double LimitHiHi { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is above the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesHi { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesLo { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesLoPre { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is above the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesLoLo { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesHiPre { get; set; } 

    /// <summary> 
    /// Gets or sets the dash array for the rendered line that is below the limit (overrides <see cref="LineStyle" />). 
    /// </summary> 
    /// <value>The dash array.</value> 
    /// <remarks>If this is not <c>null</c> it overrides the <see cref="LineStyle" /> property.</remarks> 
    public double[] DashesHiHi { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleLoPre { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleLo { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleLoLo { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleHiPre { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleHi { get; set; } 

    /// <summary> 
    /// Gets or sets the line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle LineStyleHiHi { get; set; } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleHi 
    { 
     get 
     { 
      return this.LineStyleHi != LineStyle.Automatic ? this.LineStyleHi : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleHiHi 
    { 
     get 
     { 
      return this.LineStyleHiHi != LineStyle.Automatic ? this.LineStyleHiHi : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleHiPre 
    { 
     get 
     { 
      return this.LineStyleHiPre != LineStyle.Automatic ? this.LineStyleHiPre : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is above the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleLoPre 
    { 
     get 
     { 
      return this.LineStyleLoPre != LineStyle.Automatic ? this.LineStyleLoPre : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleLo 
    { 
     get 
     { 
      return this.LineStyleLo != LineStyle.Automatic ? this.LineStyleLo : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual line style for the part of the line that is below the limit. 
    /// </summary> 
    /// <value>The line style.</value> 
    public LineStyle ActualLineStyleLoLo 
    { 
     get 
     { 
      return this.LineStyleLoLo != LineStyle.Automatic ? this.LineStyleLoLo : LineStyle.Solid; 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is above the limit. 
    /// </summary> 
    protected double[] ActualDashArrayHi 
    { 
     get 
     { 
      return this.DashesHi ?? this.ActualLineStyleHi.GetDashArray(); 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is below the limit. 
    /// </summary> 
    protected double[] ActualDashArrayLo 
    { 
     get 
     { 
      return this.DashesLo ?? this.ActualLineStyleLo.GetDashArray(); 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is below the limit. 
    /// </summary> 
    protected double[] ActualDashArrayLoPre 
    { 
     get 
     { 
      return this.DashesLoPre ?? this.ActualLineStyleLoPre.GetDashArray(); 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is above the limit. 
    /// </summary> 
    protected double[] ActualDashArrayHiHi 
    { 
     get 
     { 
      return this.DashesHiHi ?? this.ActualLineStyleHiHi.GetDashArray(); 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is below the limit. 
    /// </summary> 
    protected double[] ActualDashArrayLoLo 
    { 
     get 
     { 
      return this.DashesLoLo ?? this.ActualLineStyleLoLo.GetDashArray(); 
     } 
    } 

    /// <summary> 
    /// Gets the actual dash array for the line that is below the limit. 
    /// </summary> 
    protected double[] ActualDashArrayHiPre 
    { 
     get 
     { 
      return this.DashesHiPre ?? this.ActualLineStyleHiPre.GetDashArray(); 
     } 
    } 


    /// <summary> 
    /// Sets the default values. 
    /// </summary> 
    protected internal override void SetDefaultValues() 
    { 
     base.SetDefaultValues(); 

     if (this.ColorLoPre.IsAutomatic()) 
     { 
      this.defaultColorLoPre = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleLoPre == LineStyle.Automatic) 
     { 
      this.LineStyleLoPre = this.PlotModel.GetDefaultLineStyle(); 
     } 

     if (this.ColorHiPre.IsAutomatic()) 
     { 
      this.defaultColorHiPre = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleHiPre == LineStyle.Automatic) 
     { 
      this.LineStyleHiPre = this.PlotModel.GetDefaultLineStyle(); 
     } 

     if (this.ColorLo.IsAutomatic()) 
     { 
      this.defaultColorLo = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleLo == LineStyle.Automatic) 
     { 
      this.LineStyleLo = this.PlotModel.GetDefaultLineStyle(); 
     } 

     if (this.ColorLoLo.IsAutomatic()) 
     { 
      this.defaultColorLoLo = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleLoLo == LineStyle.Automatic) 
     { 
      this.LineStyleLoLo = this.PlotModel.GetDefaultLineStyle(); 
     } 

     if (this.ColorHi.IsAutomatic()) 
     { 
      this.defaultColorHi = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleHi == LineStyle.Automatic) 
     { 
      this.LineStyleHi = this.PlotModel.GetDefaultLineStyle(); 
     } 

     if (this.ColorHiHi.IsAutomatic()) 
     { 
      this.defaultColorHiHi = this.PlotModel.GetDefaultColor(); 
     } 

     if (this.LineStyleHiHi == LineStyle.Automatic) 
     { 
      this.LineStyleHiHi = this.PlotModel.GetDefaultLineStyle(); 
     } 
    } 

    /// <summary> 
    /// Renders the smoothed line. 
    /// </summary> 
    /// <param name="rc">The render context.</param> 
    /// <param name="clippingRect">The clipping rectangle.</param> 
    /// <param name="pointsToRender">The points.</param> 
    protected override void RenderLine(IRenderContext rc, OxyRect clippingRect, IList<ScreenPoint> pointsToRender) 
    { 
     var bottom = clippingRect.Bottom; 
     var top = clippingRect.Top; 

     // todo: this does not work when y axis is reversed 
     var yLoPre = this.YAxis.Transform(this.LimitLoPre); 
     var yLo = this.YAxis.Transform(this.LimitLo); 
     var yLoLo = this.YAxis.Transform(this.LimitLoLo); 
     var yHiPre = this.YAxis.Transform(this.LimitHiPre); 
     var yHi = this.YAxis.Transform(this.LimitHi); 
     var yHiHi = this.YAxis.Transform(this.LimitHiHi); 

     if (yLoPre< clippingRect.Top) 
     { 
      yLoPre = clippingRect.Top; 
     } 

     if (yLoPre > clippingRect.Bottom) 
     { 
      yLoPre = clippingRect.Bottom; 
     } 

     if (yHiPre < clippingRect.Top) 
     { 
      yHiPre = clippingRect.Top; 
     } 

     if (yHiPre > clippingRect.Bottom) 
     { 
      yHiPre = clippingRect.Bottom; 
     } 

     if (yLo < clippingRect.Top) 
     { 
      yLo = clippingRect.Top; 
     } 

     if (yLo > clippingRect.Bottom) 
     { 
      yLo = clippingRect.Bottom; 
     } 

     if (yLoLo < clippingRect.Top) 
     { 
      yLoLo = clippingRect.Top; 
     } 

     if (yLoLo > clippingRect.Bottom) 
     { 
      yLoLo = clippingRect.Bottom; 
     } 

     if (yHi < clippingRect.Top) 
     { 
      yHi = clippingRect.Top; 
     } 

     if (yHi > clippingRect.Bottom) 
     { 
      yHi = clippingRect.Bottom; 
     } 

     if (yHiHi < clippingRect.Top) 
     { 
      yHiHi = clippingRect.Top; 
     } 

     if (yHiHi > clippingRect.Bottom) 
     { 
      yHiHi = clippingRect.Bottom; 
     } 

     clippingRect = new OxyRect(clippingRect.Left, top, clippingRect.Width, yHiHi - top); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorHiHi), 
      this.StrokeThickness, 
      this.ActualDashArrayHiHi, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yHiHi, clippingRect.Width, yHi - yHiHi); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorHi), 
      this.StrokeThickness, 
      this.ActualDashArrayHi, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yHi, clippingRect.Width, yHiPre - yHi); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorHiPre), 
      this.StrokeThickness, 
      this.ActualDashArrayHiPre, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yHiPre, clippingRect.Width, yLoPre - yHiPre); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColor), 
      this.StrokeThickness, 
      this.ActualDashArray, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yLoPre, clippingRect.Width, yLo - yLoPre); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorLoPre), 
      this.StrokeThickness, 
      this.ActualDashArrayLoPre, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yLo, clippingRect.Width, yLoLo - yLo); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorLo), 
      this.StrokeThickness, 
      this.ActualDashArrayLo, 
      this.LineJoin, 
      false); 

     clippingRect = new OxyRect(clippingRect.Left, yLoLo, clippingRect.Width, bottom - yLoLo); 

     rc.DrawClippedLine(
      clippingRect, 
      pointsToRender, 
      this.MinimumSegmentLength * this.MinimumSegmentLength, 
      this.GetSelectableColor(this.ActualColorLoLo), 
      this.StrokeThickness, 
      this.ActualDashArrayLoLo, 
      this.LineJoin, 
      false); 
    } 
} 

}

回答

2

閱讀並在兩天內與oxyplot源代碼的掙扎後,我終於修改現有oxyplot RangeColorAxis.cs,也使一個WPF包裝。這些行動後,我可以通過使用2重建DLL(OxyPlot.dll和Oxyplot.Wpf.dll)文件得到以下圖像。

LineSeries with axis value based range colors

修改RangeColorAxis.cs

namespace OxyPlot.Axes 
{ 
    using System; 
    using System.Collections.Generic; 

    /// <summary> 
    /// Represents a color axis that contains colors for specified ranges. 
    /// </summary> 
    public class RangeColorAxis : LinearAxis, IColorAxis 
    { 
     /// <summary> 
     /// The ranges 
     /// </summary> 
     private readonly List<ColorRange> ranges = new List<ColorRange>(); 

     /// <summary> 
     /// Initializes a new instance of the <see cref="RangeColorAxis" /> class. 
     /// </summary> 
     public RangeColorAxis() 
     { 
      this.Position = AxisPosition.None; 
      this.AxisDistance = 20; 

      this.LowColor = OxyColors.Undefined; 
      this.HighColor = OxyColors.Undefined; 
      this.InvalidNumberColor = OxyColors.Gray; 

      this.IsPanEnabled = false; 
      this.IsZoomEnabled = false; 
     } 

     /// <summary> 
     /// Gets or sets the color used to represent NaN values. 
     /// </summary> 
     /// <value>A <see cref="OxyColor" /> that defines the color. The default value is <c>OxyColors.Gray</c>.</value> 
     public OxyColor InvalidNumberColor { get; set; } 

     /// <summary> 
     /// Gets or sets the color of values above the maximum value. 
     /// </summary> 
     /// <value>The color of the high values.</value> 
     public OxyColor HighColor { get; set; } 

     /// <summary> 
     /// Gets or sets the color of values below the minimum value. 
     /// </summary> 
     /// <value>The color of the low values.</value> 
     public OxyColor LowColor { get; set; } 

     /// <summary> 
     /// Adds a range. 
     /// </summary> 
     /// <param name="lowerBound">The lower bound.</param> 
     /// <param name="upperBound">The upper bound.</param> 
     /// <param name="color">The color.</param> 
     public void AddRange(double lowerBound, double upperBound, OxyColor color) 
     { 
      this.ranges.Add(new ColorRange { LowerBound = lowerBound, UpperBound = upperBound, Color = color }); 
     } 

     /// <summary> 
     /// Clears the ranges. 
     /// </summary> 
     public void ClearRanges() 
     { 
      this.ranges.Clear(); 
     } 

     /// <summary> 
     /// Gets the palette index of the specified value. 
     /// </summary> 
     /// <param name="value">The value.</param> 
     /// <returns>The palette index.</returns> 
     /// <remarks>If the value is less than minimum, 0 is returned. If the value is greater than maximum, Palette.Colors.Count+1 is returned.</remarks> 
     public int GetPaletteIndex(double value) 
     { 
      if (!this.LowColor.IsUndefined() && value < this.ranges[0].LowerBound) 
      { 
       return -1; 
      } 

      if (!this.HighColor.IsUndefined() && value > this.ranges[this.ranges.Count - 1].UpperBound) 
      { 
       return this.ranges.Count; 
      } 

      // TODO: change to binary search? 
      for (int i = 0; i < this.ranges.Count; i++) 
      { 
       var range = this.ranges[i]; 
       if (range.LowerBound <= value && range.UpperBound > value) 
       { 
        return i; 
       } 
      } 

      return int.MinValue; 
     } 

     /// <summary> 
     /// Gets the color. 
     /// </summary> 
     /// <param name="paletteIndex">The color map index.</param> 
     /// <returns>The color.</returns> 
     public OxyColor GetColor(int paletteIndex) 
     { 
      if (paletteIndex == int.MinValue) 
      { 
       return this.InvalidNumberColor; 
      } 

      if (paletteIndex == -1) 
      { 
       return this.LowColor; 
      } 

      if (paletteIndex == this.ranges.Count) 
      { 
       return this.HighColor; 
      } 

      return this.ranges[paletteIndex].Color; 
     } 

     /// <summary> 
     /// Renders the axis on the specified render context. 
     /// </summary> 
     /// <param name="rc">The render context.</param> 
     /// <param name="pass">The render pass.</param> 
     public override void Render(IRenderContext rc, int pass) 
     { 
      if (this.Position == AxisPosition.None) 
      { 
       return; 
      } 

      if (pass == 0) 
      { 
       double distance = this.AxisDistance; 
       double left = this.PlotModel.PlotArea.Left; 
       double top = this.PlotModel.PlotArea.Top; 
       double width = this.MajorTickSize - 2; 
       double height = this.MajorTickSize - 2; 
       double plotwidth = this.PlotModel.PlotArea.Width; 
       double plotheight = this.PlotModel.PlotArea.Height; 

       const int TierShift = 0; 

       switch (this.Position) 
       { 
        case AxisPosition.Left: 
         left = this.PlotModel.PlotArea.Left - TierShift - width - distance; 
         top = this.PlotModel.PlotArea.Top; 
         break; 
        case AxisPosition.Right: 
         left = this.PlotModel.PlotArea.Right + TierShift + distance; 
         top = this.PlotModel.PlotArea.Top; 
         break; 
        case AxisPosition.Top: 
         left = this.PlotModel.PlotArea.Left; 
         top = this.PlotModel.PlotArea.Top - TierShift - height - distance; 
         break; 
        case AxisPosition.Bottom: 
         left = this.PlotModel.PlotArea.Left; 
         top = this.PlotModel.PlotArea.Bottom + TierShift + distance; 
         break; 
       } 

       Action<double, double, OxyColor> drawColorRect = (ylow, yhigh, color) => 
       { 
        double ymin = Math.Min(ylow, yhigh); 
        double ymax = Math.Max(ylow, yhigh); 
        rc.DrawRectangle(
         this.IsHorizontal() 
          ? new OxyRect(ymin, top, ymax - ymin, plotheight) 
          : new OxyRect(left, ymin, plotwidth, ymax - ymin), 
         color, 
         OxyColors.Undefined); 
       }; 

       // if the axis is reversed then the min and max values need to be swapped. 
       double effectiveMaxY = this.Transform(this.IsReversed ? this.ActualMinimum : this.ActualMaximum); 
       double effectiveMinY = this.Transform(this.IsReversed ? this.ActualMaximum : this.ActualMinimum); 

       foreach (ColorRange range in this.ranges) 
       { 
        double ylow = this.Transform(range.LowerBound); 
        double yhigh = this.Transform(range.UpperBound); 

        if (this.IsHorizontal()) 
        { 
         if (ylow < effectiveMinY) 
         { 
          ylow = effectiveMinY; 
         } 

         if (yhigh > effectiveMaxY) 
         { 
          yhigh = effectiveMaxY; 
         } 
        } 
        else 
        { 
         if (ylow > effectiveMinY) 
         { 
          ylow = effectiveMinY; 
         } 

         if (yhigh < effectiveMaxY) 
         { 
          yhigh = effectiveMaxY; 
         } 
        } 

        drawColorRect(ylow, yhigh, range.Color); 
       } 

       double highLowLength = 10; 
       if (this.IsHorizontal()) 
       { 
        highLowLength *= -1; 
       } 

       if (!this.LowColor.IsUndefined()) 
       { 
        double ylow = this.Transform(this.ActualMinimum); 
        drawColorRect(ylow, ylow + highLowLength, this.LowColor); 
       } 

       if (!this.HighColor.IsUndefined()) 
       { 
        double yhigh = this.Transform(this.ActualMaximum); 
        drawColorRect(yhigh, yhigh - highLowLength, this.HighColor); 
       } 
      } 

      var r = new HorizontalAndVerticalAxisRenderer(rc, this.PlotModel); 
      r.Render(this, pass); 
     } 

     /// <summary> 
     /// Defines a range. 
     /// </summary> 
     private class ColorRange 
     { 
      /// <summary> 
      /// Gets or sets the color. 
      /// </summary> 
      /// <value>The color.</value> 
      public OxyColor Color { get; set; } 

      /// <summary> 
      /// Gets or sets the lower bound. 
      /// </summary> 
      /// <value>The lower bound.</value> 
      public double LowerBound { get; set; } 

      /// <summary> 
      /// Gets or sets the upper bound. 
      /// </summary> 
      /// <value>The upper bound.</value> 
      public double UpperBound { get; set; } 
     } 
    } 
} 

WPF包裝器RangeColorAxis.cs

namespace OxyPlot.Wpf 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Linq; 
    using System.Windows; 
    using System.Windows.Markup; 
    using System.Windows.Media; 

    /// <summary> 
    /// This is a WPF wrapper for the <see cref="OxyPlot.Axes.RangeColorAxis"/> 
    /// </summary> 
    public class RangeColorAxis : Axis 
    { 
     /// <summary> 
     /// Identifies the <see cref="InvalidNumberColor"/> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty InvalidNumberColorProperty = 
      DependencyProperty.Register(
       "InvalidNumberColor", 
       typeof(Color), 
       typeof(RangeColorAxis), 
       new PropertyMetadata(Colors.Orange, AppearanceChanged)); 

     /// <summary> 
     /// Identifies the <see cref="HighColor"/> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty HighColorProperty = DependencyProperty.Register(
      "HighColor", typeof(Color), typeof(RangeColorAxis), new PropertyMetadata(Colors.White, AppearanceChanged)); 

     /// <summary> 
     /// Identifies the <see cref="LowColor"/> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty LowColorProperty = DependencyProperty.Register(
      "LowColor", typeof(Color), typeof(RangeColorAxis), new PropertyMetadata(Colors.Black, AppearanceChanged)); 

     /// <summary> 
     /// Identifies the <see cref="Ranges"/> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty RangesProperty = DependencyProperty.Register(
      "Ranges", typeof(IList<Tuple<double, double, Color>>), typeof(RangeColorAxis), new PropertyMetadata(new List<Tuple<double,double,Color>>(), DataChanged)); 

     /// <summary> 
     /// Initializes a new instance of the <see cref="RangeColorAxis"/> class. 
     /// </summary> 
     public RangeColorAxis() 
     { 
      this.InternalAxis = new Axes.RangeColorAxis(); 
     } 

     /// <summary> 
     /// Initializes a new instance of the <see cref="InvalidNumberColor"/> class. 
     /// </summary> 
     public Color InvalidNumberColor 
     { 
      get 
      { 
       return (Color)this.GetValue(InvalidNumberColorProperty); 
      } 

      set 
      { 
       this.SetValue(InvalidNumberColorProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets the high color. 
     /// </summary> 
     public Color HighColor 
     { 
      get 
      { 
       return (Color)this.GetValue(HighColorProperty); 
      } 

      set 
      { 
       this.SetValue(HighColorProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets the low color. 
     /// </summary> 
     public Color LowColor 
     { 
      get 
      { 
       return (Color)this.GetValue(LowColorProperty); 
      } 

      set 
      { 
       this.SetValue(LowColorProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets Labels. 
     /// </summary> 
     public IList<Tuple<double, double, Color>> Ranges 
     { 
      get 
      { 
       return (IList<Tuple<double, double, Color>>)this.GetValue(RangesProperty); 
      } 

      set 
      { 
       this.SetValue(RangesProperty, value); 
      } 
     } 

     /// <summary> 
     /// Creates the model. 
     /// </summary> 
     /// <returns> 
     /// An axis object. 
     /// </returns> 
     public override Axes.Axis CreateModel() 
     { 
      this.SynchronizeProperties(); 
      return this.InternalAxis; 
     } 

     /// <summary> 
     /// Synchronizes the properties. 
     /// </summary> 
     protected override void SynchronizeProperties() 
     { 
      base.SynchronizeProperties(); 
      var axis = this.InternalAxis as Axes.RangeColorAxis; 
      Trace.Assert(axis != null); 
      //if (this.GradientStops != null) 
      //{ 
      // axis.Palette = this.GradientStops.Count > 2 
      //      ? Interpolate(this.GradientStops.ToList(), this.PaletteSize) 
      //      : new OxyPalette(); 
      //} 

      axis.HighColor = this.HighColor.ToOxyColor(); 
      axis.LowColor = this.LowColor.ToOxyColor(); 
      axis.InvalidNumberColor = this.InvalidNumberColor.ToOxyColor(); 
      axis.Minimum = this.Minimum; 
      axis.Maximum = this.Maximum; 
      if (Ranges != null) 
      { 
       axis.ClearRanges(); 
       foreach (var range in Ranges) 
       { 
        axis.AddRange(range.Item1, range.Item2, range.Item3.ToOxyColor()); 
       } 
      } 
     } 

    } 
} 

XAML文件:

<oxyPlot:Plot.Axes> 
    <oxyPlot:DateTimeAxis StringFormat="HH:mm:ss"></oxyPlot:DateTimeAxis> 
    <oxyPlot:RangeColorAxis 
     Ranges="{Binding ColorRanges}" 
     Unit="{Binding Unit}" 
     AbsoluteMinimum="{Binding DisplayMin}" 
     AbsoluteMaximum="{Binding DisplayMax}" 
     MinimumRange="{Binding DisplayMax}"/> 
</oxyPlot:Plot.Axes> 

視圖模型

... 
/// <summary> 
/// The <see cref="ColorRanges" /> property's name. 
/// </summary> 
public const string ColorRangesPropertyName = "ColorRanges"; 

private List<Tuple<double, double, System.Windows.Media.Color>> _colorRanges = new List<Tuple<double, double, System.Windows.Media.Color>>(); 

/// <summary> 
/// Sets and gets the ColorRanges property. 
/// Changes to that property's value raise the PropertyChanged event. 
/// </summary> 
public List<Tuple<double, double, System.Windows.Media.Color>> ColorRanges 
{ 
    get 
    { 
     return _colorRanges; 
    } 

    set 
    { 
     if (_colorRanges == value) 
     { 
      return; 
     } 

     _colorRanges = value; 
     RaisePropertyChanged(ColorRangesPropertyName); 
    } 
} 
... 
//usage 
ColorRanges.Clear(); 
if (DisplayMin < LevelThresholdLoLo) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(DisplayMin, LevelThresholdLoLo, Color.FromArgb(127,255,68,0))); 
} 
if (LevelThresholdLoLo < LevelThresholdLo) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLoLo, LevelThresholdLo, Color.FromArgb(127, 255, 140, 0))); 
} 
if (LevelThresholdLo < LevelThresholdLoPre) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLo, LevelThresholdLoPre, Color.FromArgb(127, 65,105,225))); 
} 
if (LevelThresholdLoPre < LevelThresholdHiPre) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdLoPre, LevelThresholdHiPre, Color.FromArgb(127, 50, 205, 50))); 
} 
if (LevelThresholdHiPre < LevelThresholdHi) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHiPre, LevelThresholdHi, Color.FromArgb(127, 65, 105, 225))); 
} 
if (LevelThresholdHi < LevelThresholdHiHi) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHi, LevelThresholdHiHi, Color.FromArgb(127,255,140,0))); 
} 
if (LevelThresholdHiHi < DisplayMax) 
{ 
    ColorRanges.Add(new Tuple<double, double, Color>(LevelThresholdHiHi, DisplayMax, Color.FromArgb(127, 255, 68, 0))); 
}