• WPF实现仪表盘(刻度跟随)


    WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织

    每日一笑

                刚和另一位摸鱼大户同事聊天,说起业余爱好。我:“我下班就看看电影打打游戏,你呢?”同事:“帮人做网站挣点外快,另外最近我目前在做一个区块链的创业项目,已经占我总收入10%了 。我有时候回复工作消息慢就是在搞这个。”感觉被背叛了,原来只有我是傻呵呵地真摸鱼。

    前言 

          需要实现仪表盘。

    欢迎转发、分享、点赞,谢谢大家~。  

    效果预览(更多效果请下载源码体验):

    一、DashboardControl.cs 代码如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using WpfDashboard.Models;
    
    namespace WpfDashboard
    {
        public class DashboardControl : ProgressBar
        {
            public DashboardControl()
            {
                this.ValueChanged += CircularProgressBar_ValueChanged;
            }
    
            void CircularProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                DashboardControl bar = sender as DashboardControl;
                double currentAngle = bar.Angle;
                double targetAngle = e.NewValue / bar.Maximum * 180;
                Angle = targetAngle;
                if (ScaleArray == null)
                    ArrayList();
                var count = Convert.ToInt32(Angle / (180 / ScaleNum));
                ScaleArray.ToList().ForEach(y =>
                {
                    y.Background = Brushes.White;
                });
    
                Brush color = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF19DCF0"));
                ScaleArray.Where(x => x.Index <= count).ToList().ForEach(y =>
                {
    
                    y.Background = color;
                });
            }
    
            public double Angle
            {
                get { return (double)GetValue(AngleProperty); }
                set { SetValue(AngleProperty, value); }
            }
    
            public static readonly DependencyProperty AngleProperty =
                DependencyProperty.Register("Angle", typeof(double), typeof(DashboardControl), new PropertyMetadata(0.0));
    
            public IList<ScaleModel> ScaleArray
            {
                get { return (IList<ScaleModel>)GetValue(ScaleArrayProperty); }
                private set { SetValue(ScaleArrayProperty, value); }
            }
    
            public static readonly DependencyProperty ScaleArrayProperty =
                DependencyProperty.Register("ScaleArray", typeof(IList<ScaleModel>), typeof(DashboardControl), new PropertyMetadata(null));
    
            public int ScaleNum
            {
                get { return (int)GetValue(ScaleNumProperty); }
                set { SetValue(ScaleNumProperty, value); }
            }
    
            public static readonly DependencyProperty ScaleNumProperty =
                DependencyProperty.Register("ScaleNum", typeof(int), typeof(DashboardControl), new PropertyMetadata(18));
            void ArrayList()
            {
                List<ScaleModel> shortticks = new List<ScaleModel>();
                for (int i = 0; i < ScaleNum; i++)
                {
                    shortticks.Add(new ScaleModel { Index = i, Background = Brushes.White });
                }
                this.ScaleArray = shortticks;
            }
        }
    }

    二、App.xaml 代码如下

    <Application x:Class="WpfDashboard.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:ec="http://schemas.microsoft.com/expression/2010/controls" 
                 xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
                 xmlns:local="clr-namespace:WpfDashboard"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            
            <LinearGradientBrush x:Key="NormalBrush" EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF164DA7"/>
                <GradientStop Color="#FF19DCF0" Offset="1"/>
            </LinearGradientBrush>
            <Style TargetType="local:DashboardControl">
                <Setter Property="Maximum" Value="100"/>
                <Setter Property="Background" Value="#252525"/>
                <Setter Property="Width" Value="200"/>
                <Setter Property="Height" Value="200"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="local:DashboardControl">
                            <Viewbox>
                                <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
                                        Background="{TemplateBinding Background}"
                                      RenderTransformOrigin="0.5,0.5">
                                    <Grid.RenderTransform>
                                        <TransformGroup>
                                            <RotateTransform Angle="-90"/>
                                        </TransformGroup>
                                    </Grid.RenderTransform>
                                    <ed:Arc  ArcThickness="8" ArcThicknessUnit="Pixel" Fill="White"
                                             RenderTransformOrigin="0.5,0.5" 
                                             StartAngle="0"
                                             EndAngle="180"
                                             Stretch="None"
                                             Margin="10"/>
                                    <ed:Arc x:Name="PART_PathBackground" Margin="24" ArcThickness="0" ArcThicknessUnit="Pixel"
                                            EndAngle="180"
                                            StartAngle="0"
                                            Stretch="None" />
                                   
                                    <ed:Arc ArcThickness="8" ArcThicknessUnit="Pixel" 
                                            Fill="{StaticResource NormalBrush}"
                                            StartAngle="0"
                                            EndAngle="{Binding Angle, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
                                            Stretch="None" 
                                            Margin="10"/>
    
                                    <ec:PathListBox IsHitTestVisible="False"
                                ItemsSource="{Binding ScaleArray,RelativeSource={RelativeSource FindAncestor,AncestorType=ProgressBar}}">
                                        <ec:PathListBox.ItemTemplate>
                                            <DataTemplate>
                                                <Border Width="2" Height="8" Background="{Binding Background}" SnapsToDevicePixels="True"
                                        UseLayoutRounding="True" />
                                            </DataTemplate>
                                        </ec:PathListBox.ItemTemplate>
                                        <ec:PathListBox.LayoutPaths>
                                            <ec:LayoutPath Distribution="Even" Orientation="OrientToPath"
                                           SourceElement="{Binding ElementName=PART_PathBackground}" />
                                        </ec:PathListBox.LayoutPaths>
                                    </ec:PathListBox>
                                    <Border RenderTransformOrigin="0.5,0.5" Margin="30,0,0,0">
                                        <Border.RenderTransform>
                                            <TransformGroup>
                                                <RotateTransform Angle="90"/>
                                            </TransformGroup>
                                        </Border.RenderTransform>
                                        <TextBlock Foreground="{StaticResource NormalBrush}"
                                                   FontSize="40"
                                                   HorizontalAlignment="Center" VerticalAlignment="Center"
                                                   Text="{Binding Path=Value, StringFormat={}{0}%, 
                                                        RelativeSource={RelativeSource TemplatedParent}}"
                                                   FontWeight="Bold" FontFamily="Agency FB"/>
                                    </Border>
    
                                </Grid>
                            </Viewbox>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
    </Style>
        </Application.Resources>
    </Application>

    三、MainWindow.xaml 代码如下

    <Window x:Class="WpfDashboard.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfDashboard"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid>
            <StackPanel VerticalAlignment="Center">
                <local:DashboardControl Value="{Binding ElementName=CirularSlider,Path=Value}"/>
                <Slider Minimum="0" Maximum="100" Margin="0,10"
                        x:Name="CirularSlider" IsSnapToTickEnabled="True"
                        VerticalAlignment="Center" Value="10" Width="220"/>
            </StackPanel>
        </Grid>
    </Window>

    更多教程欢迎关注微信公众号:

    WPF开发者QQ群: 340500857 

    blogs: https://www.cnblogs.com/yanjinhua/p/14345136.html

    源码Github:https://github.com/yanjinhuagood/WPFDevelopers.git

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

  • 相关阅读:
    SparkSQL UDF使用方法与原理详解
    Hadoop 之日志管理—应用在 YARN 中运行时的日志
    圣诞节雪花效果,pc端
    转 redis使用场景 简介
    转 springboot 教程
    springboot freeMarker
    springboot web 服务器选择
    springboot 异步任务
    springboot 整合 rabbitmq
    软件开发生命周期过程中,必须考虑的安全问题
  • 原文地址:https://www.cnblogs.com/yanjinhua/p/15015605.html
Copyright © 2020-2023  润新知