0

这是我的自定义控件,它是一种简单的进度条:

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace eg.BJM.Controls
{
    public class HorizontalBarGauge : Canvas
    {
        public HorizontalBarGauge()
        {
            IsSigned = true;
            MinValue = -100;
            MaxValue = 100;
            Value = 25;
            MarkerValue = -1;
            BorderColor = Colors.Black;
            MarkerColor = Colors.Red;
            BarColor = Colors.SkyBlue;
            BaseColor = Colors.DodgerBlue;
            ValueColor = Colors.White;
        }

        #region Dependecy Properties

        public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(int), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty MinValueProperty =
        DependencyProperty.Register("MinValue", typeof(int), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty MaxValueProperty =
        DependencyProperty.Register("MaxValue", typeof(int), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty MarkerValueProperty =
        DependencyProperty.Register("MarkerValue", typeof(int), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty MarkerColorProperty =
        DependencyProperty.Register("MarkerColor", typeof(Color), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty BaseColorProperty =
        DependencyProperty.Register("BaseColor", typeof(Color), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty BarColorProperty =
        DependencyProperty.Register("BarColor", typeof(Color), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty BorderColorProperty =
        DependencyProperty.Register("BorderColor", typeof(Color), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty BorderThicknessProperty =
        DependencyProperty.Register("BorderThickness", typeof(double), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty IsSignedProperty =
        DependencyProperty.Register("IsSigned", typeof(bool), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty ShowValueProperty =
        DependencyProperty.Register("ShowValue", typeof(bool), typeof(HorizontalBarGauge));

    public static readonly DependencyProperty ValueColorProperty =
        DependencyProperty.Register("ValueColor", typeof(Color), typeof(HorizontalBarGauge));

    #endregion

    [Description("Determines whether the bar shows [min,max] or [-max,+max]")]
    public bool IsSigned
    {
        get { return (bool)GetValue( IsSignedProperty ); }    
        set
        {
            SetValue( IsSignedProperty, value );
            if (value)
            {
                MinValue = -MaxValue;
            }
            else
            {
                MinValue = 0;
            }
            reassertValues();
            InvalidateVisual();
        }
    }

    [Description("Get/set the current value to show.")]
    public int Value
    {
        get { return (int)GetValue(ValueProperty); }
        set
        {
            SetValue( ValueProperty, value );
            InvalidateVisual();
        }
    }

    [Description("Get/set the minimum value to show.")]
    public int MinValue
    {
        get { return (int)GetValue(MinValueProperty); }
        set
        {
            SetValue(MinValueProperty, value);
            reassertValues();
            InvalidateVisual();
        }
    }

    [Description("Get/set the maximum value to show.")]
    public int MaxValue
    {
        get { return (int)GetValue(MaxValueProperty); }
        set
        {
            value = Math.Max(value, 1);
            SetValue(MaxValueProperty, value);
            reassertValues();
            InvalidateVisual();
        }
    }

    [Description("Get/set the marker value to show. Negative => no marker.")]
    public int MarkerValue
    {
        get { return (int)GetValue(MarkerValueProperty); }
        set
        {
            SetValue(MaxValueProperty, value);
            reassertValues();
            InvalidateVisual();
        }
    }

    [Description("Get/set the color of the marker.")]
    public Color MarkerColor
    {
        get { return (Color)GetValue(MarkerColorProperty); }
        set
        {
            SetValue(MarkerColorProperty, value);
            Brush penBrush = new SolidColorBrush( value );
            _markerPen = new Pen( penBrush, 3 );
        }
    }

    [Description("Get/set the value text color.")]
    public Color ValueColor
    {
        get { return (Color)GetValue(ValueColorProperty); }
        set
        {
            SetValue(ValueColorProperty, value);
            _textBrush = new SolidColorBrush(value);
        }
    }


    [Description("Get/set the base color.")]
    public Color BaseColor
    {
        get { return (Color)GetValue(BaseColorProperty); }
        set
        {
            SetValue(BaseColorProperty, value);
            _bodyBrush = new SolidColorBrush( value );
        }
    }

    [Description("Get/set the bar color.")]
    public Color BarColor
    {
        get { return (Color)GetValue(BarColorProperty); }
        set
        {
            SetValue(BarColorProperty, value);
            _barBrush = new SolidColorBrush( value );
        }
    }

    [Description("Get/set the border color.")]
    public Color BorderColor
    {
        get { return (Color)GetValue(BorderColorProperty); }
        set
        {
            SetValue(BorderColorProperty, value);
            var brush = new SolidColorBrush( value );
            _borderPen = new Pen( brush, BorderThickness );
        }
    }

    [Description("Get/set the border thickness.")]
    public double BorderThickness
    {
        get { return (double)GetValue(BorderThicknessProperty); }
        set
        {
            SetValue(BorderThicknessProperty, value);
            var brush = new SolidColorBrush( BorderColor );
            _borderPen = new Pen( brush, value );
        }
    }

    [Description("Get/set whether values are displayed in the control.")]
    public bool ShowValue
    {
        get { return (bool)GetValue( ShowValueProperty ); }
        set { SetValue( ShowValueProperty, value );}
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);

        // Background.
        drawingContext.DrawRectangle(_bodyBrush, null, _rectangle);

        // Bar.
        int value = Value;
        if (value != 0)
        {
            Rect barRect;
            if (IsSigned)
            {
                double frac = Convert.ToDouble(value)/Convert.ToDouble(MaxValue*2);
                if (value < 0)
                {
                    barRect = new Rect(_rectangle.Width/2-frac*_rectangle.Width, 0, _rectangle.Width/2, _rectangle.Height);
                }
                else
                {
                    barRect = new Rect( _rectangle.Width/2, 0, frac*_rectangle.Width, _rectangle.Height );
                }

                drawingContext.DrawRectangle( _barBrush, null, barRect );
            }
            else
            {
                double x = (_rectangle.Width*value)/(MaxValue - MinValue);
                if (x > 0)
                {
                    barRect = new Rect( 0, 0, x, _rectangle.Height );
                    drawingContext.DrawRectangle( _barBrush, null, barRect );
                }
            }
        }

        // Marker.
        if (MarkerValue >= 0)
        {
            if (IsSigned)
            {
                double frac = Convert.ToDouble( MarkerValue )/Convert.ToDouble( MaxValue );
                double markerX1 = 0.5*_rectangle.Width*(1 + frac);
                Point p0 = new Point( markerX1, 0 );
                Point p1 = new Point( markerX1, _rectangle.Height );
                drawingContext.DrawLine( _markerPen, p0, p1 );
                double markerX2 = 0.5*_rectangle.Width*(1 - frac);
                Point p2 = new Point( markerX2, 0 );
                Point p3 = new Point( markerX2, _rectangle.Height );
                drawingContext.DrawLine( _markerPen, p2, p3 );
            }
            else
            {
                double markerX = (_rectangle.Width*MarkerValue)/(MaxValue - MinValue);
                Point p0 = new Point( markerX, 0 );
                Point p1 = new Point( markerX, _rectangle.Height );
                drawingContext.DrawLine( _markerPen, p0, p1 );
            }
        }

        // Border.
        drawingContext.DrawRectangle(null, _borderPen, _rectangle);

        // Text.
        if (ShowValue)
        {
            FormattedText text = new FormattedText( value.ToString(), CultureInfo.CurrentCulture,
                FlowDirection.LeftToRight, s_typeface, 12, _textBrush );
            Point pos = new Point( (_rectangle.Width - text.Width)/2, (_rectangle.Height - text.Height)/2 );
            drawingContext.DrawText( text, pos );
        }
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        _rectangle = new Rect( sizeInfo.NewSize );
        InvalidateVisual();
    }

    private int clamp(int value)
    {
        return (value < MinValue ? MinValue : value > MaxValue ? MaxValue : value);
    }

    private void reassertValues()
    {
        // Make sure max and min are correct.
        int oldMin = MinValue;
        int newMin = oldMin;

        int oldMax = MaxValue;
        int newMax = oldMax;

        if (oldMin > oldMax)
        {
            newMin = oldMax;
            newMax = oldMin;
        }

        if (newMin != oldMin)
        {
            SetValue(MinValueProperty, newMin);
        }

        if (newMax != oldMax)
        {
            SetValue(MaxValueProperty, newMax);
        }

        // Make sure value is in [min,max].
        int oldValue = Value;
        int newValue = clamp(oldValue);
        if (newValue != oldValue)
        {
            Value = newValue;
        }

        // Make sure marker is correctly placed.
        int marker = MarkerValue;
        if (marker >= 0)
        {
            int newMarker = clamp(marker);
            if (newMarker != marker)
            {
                SetValue(MarkerValueProperty, newMarker);
            }
        }
    }

    private Pen _borderPen;
    private Pen _markerPen;
    private Brush _barBrush;
    private Brush _bodyBrush;
    private Rect _rectangle;
    private Brush _textBrush;

    private static readonly Typeface s_typeface = new Typeface( "Verdana" );
}

}

这是绑定到它的 XAML:

        <controls:HorizontalBarGauge Grid.Row="1" Grid.Column="1"
                                 Margin="8" Width="130" Height="18"
                                 IsSigned="False"
                                 MinValue="0"
                                 MaxValue="100"
                                 BorderThickness="2"
                                 BorderColor="MidnightBlue"
                                 ShowValue="True"
                                 Value="{Binding StepperPosition}"
                                 />

当控件初始化时,控件显示正确的值。但是当我在后面的代码中更改“StepperPosition”属性时,没有任何变化。断点代码显示 ValueProperty 设置器不会被调用,即使 StepperPosition 执行并触发 OnPropertyChanged("StepperPosition")。INPC 属于基类。所以我想我已经排除了绑定不刷新的常见原因,现在有点难过。


周一。对了,稍微往前走。现在可以通过连接到 DepedencyPropertyChanged 回调来刷新视觉效果。@HighCore 这就是它们的样子:

酒吧

该条有两种模式:速度(需要为 +/-)和位置(始终为 +ve)。速度表中的红线显示其他地方设置的最大速度。它们是近乎实时的更新,因为它们是步进电机状态的指示器。

4

0 回答 0