WPF 使用 DrawingContext 绘制刻度条
框架使用大于等于.NET40;Visual Studio 2022;项目使用 MIT 开源许可协议;定义Interval步长、SpanInterval间隔步长、MiddleMask中间步长。当步长/ 间隔步长= 需要绘制的小刻度。循环绘制小刻度,判断当前j并取中间步长的模,如果模!=零就绘制中高线。从StartValue 开始绘制刻度到EndValue 结束刻度。CurrentGeometry 重新绘制当前刻度的Path值。CurrentValue 当前值如果发生变化时则去重新CurrentGeometry 。
1) 准备
Ruler.cs如下:
usingSystem;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Media;
namespaceWPFDevelopers.Controls
{
publicclassRuler:Control
{
publicstaticreadonlyDependencyPropertyIntervalProperty=
DependencyProperty.Register("Interval",typeof(double),typeof(Ruler),newUIPropertyMetadata(30.0));
publicstaticreadonlyDependencyPropertySpanIntervalProperty=
DependencyProperty.Register("SpanInterval",typeof(double),typeof(Rulr),newUIPropertyMetadata(5.0));
publicstaticreadonlyDependencyPropertyMiddleMaskProperty=
DependencyProperty.Register("MiddleMask",typeof(int),typeof(Ruler),newUIPropertyMetadata(2));
publicstaticreadonlyDependencyPropertyCurrentValueProperty=
DependencyProperty.Register("CurrentValue",typeof(double),typeof(Ruler),
newUIPropertyMetadata(OnCurrentValueChanged));
publicstaticreadonlyDependencyPropertyStartValueProperty=
DependencyProperty.Register("StartValue",typeof(double),typeof(Ruler),newUIPropertyMetadata(120.0));
publicstaticreadonlyDependencyPropertyEndValueProperty=
DependencyProperty.Register("EndValue",typeof(double),typeof(Ruler),newUIPropertyMetadata(240.0));
publicstaticreadonlyDependencyPropertyCurrentGeometryProperty=
DependencyProperty.Register("CurrentGeometry",typeof(Geometry),typeof(Ruler),
newPropertyMetadata(Geometry.Parse("M257,0257,25264,49250,49257,25")));
staticRuler()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Ruler),newFrameworkPropertyMetadata(typeof(Ruler)));
}
publicRuler()
{
Loaded+=Ruler_Loaded;
}
publicdoubleInterval
{
get=>(double)GetValue(IntervalProperty);
set=>SetValue(IntervalProperty,value);
}
publicdoubleSpanInterval
{
get=>(double)GetValue(SpanIntervalProperty);
set=>SetValue(SpanIntervalProperty,value);
}
publicintMiddleMask
{
get=>(int)GetValue(MiddleMaskProperty);
set=>SetValue(MiddleMaskProperty,value);
}
publicdoubleCurrentValue
{
get=>(double)GetValue(CurrentValueProperty);
set
{
SetValue(CurrentValueProperty,value);
PaintPath();
}
}
publicdoubleStartValue
{
get=>(double)GetValue(StartValueProperty);
set=>SetValue(StartValueProperty,value);
}
publicdoubleEndValue
{
get=>(double)GetValue(EndValueProperty);
set=>SetValue(EndValueProperty,value);
}
publicGeometryCurrentGeometry
{
get=>(Geometry)GetValue(CurrentGeometryProperty);
set=>SetValue(CurrentGeometryProperty,value);
}
privatestaticvoidOnCurrentValueChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
{
varruler=dasRuler;
ruler.CurrentValue=Convert.ToDouble(e.NewValue);
}
protectedoverridevoidOnRender(DrawingContextdrawingContext)
{
RenderOptions.SetEdgeMode(this,EdgeMode.Aliased);
varnextLineValue=0d;
varone_Width=ActualWidth/((EndValue-StartValue)/Interval);
for(vari=0;i<=(EndValue-StartValue)/Interval;i++)
{
varnumberText=DrawingContextHelper.GetFormattedText((StartValue+i*Interval).ToString(),
(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#FFFFFF"),FlowDirection.LeftToRight,
10);
drawingContext.DrawText(numberText,newPoint(i*one_Width-8,0));
drawingContext.DrawLine(newPen(newSolidColorBrush(Colors.White),1),newPoint(i*one_Width,25),
newPoint(i*one_Width,ActualHeight-2));
varcnt=Interval/SpanInterval;
for(varj=1;j<=cnt;j++)
if(j%MiddleMask==0)
drawingContext.DrawLine(newPen(newSolidColorBrush(Colors.White),1),
newPoint(j*(one_Width/cnt)+nextLineValue,ActualHeight-2),
newPoint(j*(one_Width/cnt)+nextLineValue,ActualHeight-10));
else
drawingContext.DrawLine(newPen(newSolidColorBrush(Colors.White),1),
newPoint(j*(one_Width/cnt)+nextLineValue,ActualHeight-2),
newPoint(j*(one_Width/cnt)+nextLineValue,ActualHeight-5));
nextLineValue=i*one_Width;
}
}
privatevoidRuler_Loaded(objectsender,RoutedEventArgse)
{
PaintPath();
}
privatevoidPaintPath()
{
vard_Value=CurrentValue-StartValue;
varone_Value=ActualWidth/(EndValue-StartValue);
varx_Point=one_Value*d_Value+((double)Parent.GetValue(ActualWidthProperty)-ActualWidth)/2d;
CurrentGeometry=
Geometry.Parse($"M{x_Point},0{x_Point},25{x_Point+7},49{x_Point-7},49{x_Point},25");
}
}
}
2) 使用
RulerControlExample.xaml.cs如下:
<UserControlx:Class="WPFDevelopers.Samples.ExampleViews.RulerControlExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
mc:Ignorable="d"
d:DesignHeight="450"d:DesignWidth="800">
<Grid>
<Sliderx:Name="PART_Slider"IsSnapToTickEnabled="True"
Value="40"
Minimum="10"
Maximum="210"/>
<UniformGridRows="3">
<GridBackground="{StaticResourceCircularDualSolidColorBrush}"Height="51"Margin="40,0">
<PathStroke="{StaticResourceSuccessPressedSolidColorBrush}"StrokeThickness="1"Fill="{StaticResourceSuccessPressedSolidColorBrush}"
Data="{BindingElementName=PART_Ruler,Path=CurrentGeometry,Mode=TwoWay}"/>
<wpfdev:Rulerx:Name="PART_Ruler"Margin="40,0"Interval="20"StartValue="10"EndValue="210"
CurrentValue="{BindingElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
</Grid>
<GridBackground="{StaticResourceDangerPressedSolidColorBrush}"Height="51"Margin="40,0">
<PathStroke="{StaticResourceSuccessPressedSolidColorBrush}"StrokeThickness="1"Fill="{StaticResourceSuccessPressedSolidColorBrush}"
Data="{BindingElementName=PART_Ruler1,Path=CurrentGeometry,Mode=TwoWay}"/>
<wpfdev:Rulerx:Name="PART_Ruler1"Margin="40,0"Interval="20"StartValue="10"EndValue="210"
CurrentValue="{BindingElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
</Grid>
<GridBackground="{StaticResourceWarningPressedSolidColorBrush}"Height="51"Margin="40,0">
<PathStroke="{StaticResourceSuccessPressedSolidColorBrush}"StrokeThickness="1"Fill="{StaticResourceSuccessPressedSolidColorBrush}"
Data="{BindingElementName=PART_Ruler2,Path=CurrentGeometry,Mode=TwoWay}"/>
<wpfdev:Rulerx:Name="PART_Ruler2"Margin="40,0"Interval="20"StartValue="10"EndValue="210"
CurrentValue="{BindingElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
</Grid>
</UniformGrid>
</Grid>
</UserControl>
以上就是WPF使用DrawingContext实现绘制刻度条的详细内容,更多关于WPF刻度条的资料请关注中国红客联盟其它相关文章!