WPF制作标尺

0792e93cc7eea4d2b9a446b5021bfd6e.png

     由于在WPF中没有现成的刻度尺控件,所以我们自己实现一个。

PS:有更好的方式欢迎推荐。

01

代码如下

一、创建 Ruler.cs 继承 Control代码如下。

1db8fa4e3fcb9e7b697c27619e9768c8.png

Ruler.cs实现思路如下

1、与前几篇思路几乎一致,不做阐述。

e601ba97c602127f8cb60bb330d60734.png

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;


namespace WPFDevelopers.Controls
{
    public class Ruler : Control
    {
       
        public static readonly DependencyProperty IntervalProperty = 
            DependencyProperty.Register("Interval", typeof(double), typeof(Ruler), new UIPropertyMetadata(30.0));


        public double Interval
        {
            get { return (double)GetValue(IntervalProperty); }


            set { SetValue(IntervalProperty, value); }
        }


        
        public static readonly DependencyProperty SpanIntervalProperty = 
            DependencyProperty.Register("SpanInterval", typeof(double), typeof(Ruler), new UIPropertyMetadata(5.0));


        public double SpanInterval
        {
            get { return (double)GetValue(SpanIntervalProperty); }


            set { SetValue(SpanIntervalProperty, value); }
        }


       
        public static readonly DependencyProperty MiddleMaskProperty = 
            DependencyProperty.Register("MiddleMask", typeof(int), typeof(Ruler), new UIPropertyMetadata(2));


        public int MiddleMask
        {
            get { return (int)GetValue(MiddleMaskProperty); }


            set { SetValue(MiddleMaskProperty, value); }
        }


        public static readonly DependencyProperty CurrentValueProperty = 
            DependencyProperty.Register("CurrentValue", typeof(double), typeof(Ruler), new UIPropertyMetadata(OnCurrentValueChanged));


        private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Ruler ruler = d as Ruler;
            ruler.CurrentValue = Convert.ToDouble(e.NewValue);
        }


        public double CurrentValue
        {
            get { return (double)GetValue(CurrentValueProperty); }


            set
            {
                SetValue(CurrentValueProperty, value);
                PaintPath();
            }
        }
        public static readonly DependencyProperty StartValueProperty = 
            DependencyProperty.Register("StartValue", typeof(double), typeof(Ruler), new UIPropertyMetadata(120.0));


        public double StartValue
        {
            get { return (double)GetValue(StartValueProperty); }


            set { SetValue(StartValueProperty, value); }
        }


        public static readonly DependencyProperty EndValueProperty = 
            DependencyProperty.Register("EndValue", typeof(double), typeof(Ruler), new UIPropertyMetadata(240.0));


        public double EndValue
        {
            get { return (double)GetValue(EndValueProperty); }


            set { SetValue(EndValueProperty, value); }
        }
       
        public static readonly DependencyProperty CurrentGeometryProperty = 
            DependencyProperty.Register("CurrentGeometry", typeof(Geometry), typeof(Ruler), new PropertyMetadata(Geometry.Parse("M 257,0 257,25 264,49 250,49 257,25")));


        public Geometry CurrentGeometry
        {
            get { return (Geometry)GetValue(CurrentGeometryProperty); }


            set { SetValue(CurrentGeometryProperty, value); }
        }
        static Ruler()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Ruler), new FrameworkPropertyMetadata(typeof(Ruler)));
        }
        protected override void OnRender(DrawingContext drawingContext)
        {
            RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
            double nextLineValue = 0d; 
            var one_Width = ActualWidth / ((EndValue - StartValue) / Interval);


            for (int i = 0; i <= ((EndValue - StartValue) / Interval); i++) 
            {
                var numberText = new FormattedText((StartValue + (i * Interval)).ToString(),
                    CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, Brushes.White);
                drawingContext.DrawText(numberText, new Point(i * one_Width - 8, 0));
                drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1), new Point(i * one_Width, 25), new Point(i * one_Width, ActualHeight - 2));
                var cnt = Interval / SpanInterval;
                for (int j = 1; j <= cnt; j++) 
                {
                    if (j % MiddleMask == 0)
                        drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1), 
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 2),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 10));
                    else
                        drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 2),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 5));
                }


                nextLineValue = i * one_Width;
            }


        }
        public Ruler()
        {
            this.Loaded += Ruler_Loaded;
        }


        private void Ruler_Loaded(object sender, RoutedEventArgs e)
        {
            PaintPath();
        }
        
        private void PaintPath()
        {
            var d_Value = CurrentValue - StartValue;
            var one_Value = ActualWidth / (EndValue - StartValue);
            double x_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");
        }


    }
}

二、创建RulerControlExample.xaml代码如下

443ac71fefb67f5f5e0cec99409b8fe1.png

<UserControl x: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/yanjinhuagood/WPFDevelopers"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Slider x:Name="PART_Slider" IsSnapToTickEnabled="True"
                Value="40"
                Minimum="10"
                Maximum="210"/>
        <UniformGrid Rows="3">
            <Grid Background="{StaticResource CircularDualSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
            <Grid Background="{StaticResource DangerPressedSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler1, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler1" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
            <Grid Background="{StaticResource WarningPressedSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler2, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler2" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
        </UniformGrid>
        
        
    </Grid>
</UserControl>

02


效果预览

鸣谢素材提供者 - 帅嘉欣

源码地址如下

github:https://github.com/yanjinhuagood/WPFDevelopers.git

gitee:https://gitee.com/yanjinhua/WPFDevelopers.git

WPF开发者QQ群: 340500857 

blogs: https://www.cnblogs.com/yanjinhua

Github:https://github.com/yanjinhuagood

出处:https://www.cnblogs.com/yanjinhua

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载请著名作者 出处 https://github.com/yanjinhuagood

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF(Windows Presentation Foundation)是一种用于创建用户界面的框架,它提供了丰富的图形、动画和多媒体功能。在WPF中,时间标尺控件和时间轴控件是用于显示和控制时间的UI元素。 时间标尺控件是一个用于在UI中显示时间范围的控件,通常以水平方向展示。它可以用来展示一个时间段内的各种事件或任务,比如流程图、计划表等。时间标尺控件通常使用刻度和刻度线来标示时间的流逝,用户可以根据需要在标尺上自定义刻度单位和刻度间隔。 时间轴控件则是一个用于以时间为基准展示事件序列的控件。它可以用于展示一个或多个事件在时间上的发生顺序,比如历史事件的时间轴、项目进度的时间轴等。时间轴控件一般以水平方向展示,可以根据时间的流逝在时间线上动态显示事件的位置和时长,并提供交互功能,比如拖动事件、缩放时间范围等。 在WPF中,可以利用内置的控件(如Canvas、Grid等)结合自定义样式和模板来创建时间标尺控件和时间轴控件。也可以使用第三方开源控件库或自行开发定制化的控件。同时,WPF还提供了数据绑定、命令、动画等特性,可以方便地与后端数据源和用户交互进行集成。 总之,WPF的时间标尺控件和时间轴控件为开发者提供了灵活、可定制的时间展示和交互方式,可以满足各种时间相关场景的需求。通过使用这些控件,开发者可以方便地实现时间范围的展示、事件的排序和交互操作,提升用户体验和界面效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值