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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章