wpf自定义带刻度的柱状图控件

效果图:

主要代码xaml:

<UserControl x:Class="INSControls._01Conning.Steer.ConningSpeedBar"
             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:ec="http://schemas.microsoft.com/expression/2010/controls"
             xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="80" Focusable="False" FocusVisualStyle="{x:Null}" Loaded="UserControl_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="40" />
        </Grid.RowDefinitions>
        <Label HorizontalAlignment="Left"
               VerticalAlignment="Center"
               Content="{Binding Title, RelativeSource={RelativeSource AncestorType=UserControl}}"
               Foreground="{Binding  LabelColor, RelativeSource={RelativeSource AncestorType=UserControl} }"
               FontFamily="微软雅黑"></Label>
        <Label HorizontalAlignment="Left"
               VerticalAlignment="Center"
               Margin="0,0,0,5"
               Foreground="#cc8800"
               FontFamily="微软雅黑"
               Content="LOG2"
               Grid.Row="1" />
        <Border Width="80"
                HorizontalAlignment="Left"
                Grid.Row="2"
                Background="#24325f">
            <Grid Margin="1,14,0,14"
                  x:Name="mainGrid">
                <!--具体的值填充的柱状图形-->
                <Grid x:Name="graphicGrid"
                      Height="10"
                      VerticalAlignment="Top"  RenderTransformOrigin="0.5,0.5">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions> 

                             <Path   Data="M40,0 L80,40 L0,40 z"
                              Fill="#cc0663c2" Stretch="Fill"  x:Name="path"  /> 

                    <Border Grid.Row="1"
                            Background="#cc0663c2" />
                    <Grid.RenderTransform>
                        <RotateTransform Angle="0" x:Name="polygonRotateAngel" />
                    </Grid.RenderTransform>
                </Grid>
                <!--短刻度-->
                <ec:PathListBox Background="Transparent"
                                x:Name="shortTicks"
                                ItemsSource="{Binding ShortTicks,RelativeSource={RelativeSource AncestorType=UserControl}}"
                                Focusable="False"
                                FocusVisualStyle="{x:Null}">
                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <Rectangle Width="1"
                                       Height="48"
                                       Margin="0,0,0,49"
                                       Fill="#b5b5b5"
                                       Focusable="False"
                                       FocusVisualStyle="{x:Null}" />
                            <!--<Border Width="1"
                                    Height="48"
                                    Background="#b5b5b5"
                                    UseLayoutRounding="True"
                                    Margin="0,0,0,49" />-->
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath  Distribution="Even"
                                        Orientation="OrientToPath"
                                        SourceElement="{Binding ElementName=ShortTickPath}" >

                        </ec:LayoutPath>
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>
                <!--  长刻度  -->
                <ec:PathListBox x:Name="LongTick"
                                IsHitTestVisible="False"
                                ItemsSource="{Binding LongTicks, RelativeSource={RelativeSource AncestorType=UserControl}}"
                                Focusable="False"
                                FocusVisualStyle="{x:Null}" >
                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <Rectangle Width="48"
                                       Height="3"
                                       Margin="48,0,0,0"
                                       Fill="White"
                                       Focusable="False"
                                       FocusVisualStyle="{x:Null}" />
                            <!--<Border Width="3"
                                    Height="48"
                                    Background="White"
                                    SnapsToDevicePixels="True"
                                    UseLayoutRounding="True"
                                    Margin="0,0,0,49">

                            </Border>-->
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath Distribution="Even"
                                       Orientation="None"
                                       SourceElement="{Binding ElementName=LongTickPath}" />
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>

                <!--  刻度上显示的数字  -->
                <ec:PathListBox IsHitTestVisible="False"
                                ItemsSource="{Binding TickMarks,RelativeSource={RelativeSource AncestorType=UserControl}}">

                    <ec:PathListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock x:Name="tb" HorizontalAlignment="Left" Foreground="White"
                                       Text="{Binding}"  RenderTransformOrigin="0,0" Margin="0,50,0,0">
                                <TextBlock.RenderTransform>
                                    <RotateTransform Angle="-90"/>
                                </TextBlock.RenderTransform>
                            </TextBlock>
                        </DataTemplate>
                    </ec:PathListBox.ItemTemplate>
                    <ec:PathListBox.LayoutPaths>
                        <ec:LayoutPath Distribution="Even"
                                       Orientation="OrientToPath"
                                       SourceElement="{Binding ElementName=NumberPath}" />
                    </ec:PathListBox.LayoutPaths>
                </ec:PathListBox>

                <Path   x:Name="LongTickPath"
                        Data="M0,0 v1"
                        VerticalAlignment="Top"
                        HorizontalAlignment="Right"
                        Stretch="Fill" Fill="Red" Stroke="Red" StrokeThickness="2"
                        Grid.RowSpan="2"
                        Margin="0,0"
                        Focusable="False"
                        FocusVisualStyle="{x:Null}" />
                <Path x:Name="ShortTickPath"
                      Data="M0,0 V1"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Left"
                      Stretch="Fill"
                      Grid.RowSpan="2"
                      Margin="0,0"
                      Focusable="False"
                      FocusVisualStyle="{x:Null}" />

                <Path x:Name="NumberPath"
                      Data="M0,0 V1"
                      Margin="45,0,0,0"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Center"
                      Stretch="Fill"
                      Grid.RowSpan="2"
                      Focusable="False"
                      FocusVisualStyle="{x:Null}"  Stroke="Yellow" StrokeThickness="1"/>

            </Grid>
        </Border>

        <StackPanel Grid.Row="3"
                    Orientation="Horizontal">
            <TextBox Width="90"
                     Height="35"
                     IsReadOnly="True"
                     Foreground="{Binding TextboxColor,RelativeSource={RelativeSource AncestorType=UserControl}}"
                     VerticalAlignment="Center"
                     Text="{ Binding CurrentValue, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Control}}" />
            <Label VerticalAlignment="Center"
                   Content="km"
                   Foreground="{Binding LabelColor, RelativeSource={RelativeSource AncestorType=UserControl}}"></Label>
        </StackPanel>

    </Grid>
</UserControl>

  .cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace INSControls._01Conning.Steer
{
    /// <summary>
    /// ConningSpeedBar.xaml 的交互逻辑
    /// </summary>
    public partial class ConningSpeedBar : UserControl
    {
        public ConningSpeedBar()
        {
            InitializeComponent();
        }

        public List<string> TickMarks
        {
            get { return (List<string>)GetValue(TickMarksProperty); }
            set { SetValue(TickMarksProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TickMarks.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TickMarksProperty =
            DependencyProperty.Register("TickMarks", typeof(List<string>), typeof(ConningSpeedBar), new PropertyMetadata(null));

        public List<object> LongTicks
        {
            get { return (List<object>)GetValue(LongTicksProperty); }
            set { SetValue(LongTicksProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LongTicks.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LongTicksProperty =
            DependencyProperty.Register("LongTicks", typeof(List<object>), typeof(ConningSpeedBar), new PropertyMetadata(null));

        public List<object> ShortTicks
        {
            get { return (List<object>)GetValue(ShortTicksProperty); }
            set { SetValue(ShortTicksProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ShortTicks.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ShortTicksProperty =
            DependencyProperty.Register("ShortTicks", typeof(List<object>), typeof(ConningSpeedBar), new PropertyMetadata(null));

        public double CurrentValue
        {
            get { return (double)GetValue(CurrentValueProperty); }
            set { SetValue(CurrentValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentValueProperty =
            DependencyProperty.Register("CurrentValue", typeof(double), typeof(ConningSpeedBar), new PropertyMetadata(0.0, CurrentValueChangeCallback));

        private static void CurrentValueChangeCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ConningSpeedBar c = d as ConningSpeedBar;
            UpdateUICurrentvalue((double)e.NewValue, c);
        }

        private static void UpdateUICurrentvalue(double currentValue, ConningSpeedBar c)
        {
            if (c.mainGrid.ActualHeight==0)
            {
                return;
            }
            if (currentValue > 0)
            {
                c.polygonRotateAngel.Angle = 0;
                double totalValue = c.MaxValue - c.MinValue;
                //计算显示图形位置
                double top = (c.MaxValue - currentValue) * c.mainGrid.ActualHeight / totalValue;
                //计算显示图形大小
                double height = currentValue * c.mainGrid.ActualHeight / totalValue;
                c.graphicGrid.Margin = new Thickness(0, top, 0, 0);
                if (height > 40)
                {
                    c.graphicGrid.Height = height;
                }
                else
                {
                    c.graphicGrid.Height = c.path.Height = height;
                }

            }
            else
            {
                c.polygonRotateAngel.Angle = 180;
                double totalValue = c.MaxValue - c.MinValue;
                //计算显示图形位置
                double top = (c.MaxValue) * c.mainGrid.ActualHeight / totalValue;
                //计算显示图形大小
                double height = -currentValue * c.mainGrid.ActualHeight / totalValue;
                c.graphicGrid.Margin = new Thickness(0, top, 0, 0);
                if (height > 40)
                {
                    c.graphicGrid.Height = height;
                }
                else
                {
                    c.graphicGrid.Height = c.path.Height = height;
                }
            }

        }

        public SolidColorBrush LabelColor
        {
            get { return (SolidColorBrush)GetValue(LabelColorProperty); }
            set { SetValue(LabelColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LabelColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LabelColorProperty =
            DependencyProperty.Register("LabelColor", typeof(SolidColorBrush), typeof(ConningSpeedBar), new PropertyMetadata(Brushes.Black));

        public SolidColorBrush TextboxColor
        {
            get { return (SolidColorBrush)GetValue(TextboxColorProperty); }
            set { SetValue(TextboxColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TextboxColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextboxColorProperty =
            DependencyProperty.Register("TextboxColor", typeof(SolidColorBrush), typeof(ConningSpeedBar), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(214, 214, 214))));

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ConningSpeedBar), new PropertyMetadata(""));

        public double MaxValue
        {
            get { return (double)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaxValueProperty =
            DependencyProperty.Register("MaxValue", typeof(double), typeof(ConningSpeedBar), new PropertyMetadata(30d));

        public double MinValue
        {
            get { return (double)GetValue(MinValueProperty); }
            set { SetValue(MinValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MinValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinValueProperty =
            DependencyProperty.Register("MinValue", typeof(double), typeof(ConningSpeedBar), new PropertyMetadata(-10d));

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            //短刻度
            List<object> shortticks = new List<object>();
            for (int i = 0; i < 50; i++)
            {
                shortticks.Add(new object());
            }
            ShortTicks = shortticks;
            //显示刻度文字
            List<string> numbers = new List<string>();
            //长刻度
            List<object> longticks = new List<object>();
            for (int i = 0; i < 5; i++)
            {
                //计算长度信息,等比例地减去间隔值
                string tickInfo = (MaxValue - i * (MaxValue - MinValue) / 4).ToString();
                numbers.Add(tickInfo+new string(‘&‘,i+1));
                longticks.Add(new object());
            }
            LongTicks = longticks;
            TickMarks = numbers;
           UpdateUICurrentvalue(CurrentValue, this) ;
        }

    }
}

  源码地址:

https://files.cnblogs.com/files/chlm/%E5%88%BB%E5%BA%A6%E7%BA%BF.rar

原文地址:https://www.cnblogs.com/chlm/p/9451536.html

时间: 2024-10-11 13:03:49

wpf自定义带刻度的柱状图控件的相关文章

【Android】Android自定义带board的圆角控件

介绍 圆角控件常用于头像,按钮,图标等,用途十分广泛,而且常常配合board使用. 在IOS中,UIVIew的CALayer层已经提供了圆角和board的方法,所以圆角控件的制作非常简单,只需要类似以下简单代码即可实现: view.layer.cornerRadius = 20; view.layer.borderColor = [UIColor yellowColor].CGColor; view.layer.borderWidth = 10; view.clipsToBounds = YES

【安卓笔记】带自定义属性的view控件

开发中经常需要自定义view控件或者组合控件,某些控件可能需要一些额外的配置.比如自定义一个标题栏,你可能需要根据不同尺寸的手机定制不同长度的标题栏,或者更常见的你需要配置标题栏的背景,这时候,你就会考虑到你写的view的扩展性问题,通常情况下,我们可以为这个自定义的标题栏加上一些setXXX方法,供外界调用,设置其颜色.长度等属性.但是我们都知道,在使用系统控件时,我们大多数情况下并不需要在代码中配置控件,而仅仅只需在布局文件中对控件宽.高.颜色等进行配置,这样做的好处就将UI与业务逻辑解耦,

WPF自定义控件与样式(10)-进度控件ProcessBar自定义样

一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: ProcessBar自定义标准样式: ProcessBar自定义环形进度样式: 二.ProcessBar标准样式 效果图: ProcessBar的样式非常简单: <!--ProgressBar Style--> <Style TargetType="ProgressBar" x

Android 自定义带刻度的seekbar

自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby.client.views.CustomSeekbar android:id="@+id/myCustomSeekBar" android:layout_width="wrap_content" android:layout_height="wrap_cont

创建一个带模版的用户控件 V.3

再重构此篇<创建一个带模版的用户控件  V.2>http://www.cnblogs.com/insus/p/4164149.html 让其它动态实现header,Item和Footer. Insus.NET不想所有代码写在InstantiateIn(Control container)方法内的switch分流上.其实是想使用开发设计模式的中介者(Mediator)来拆分它. 拆分为四个方法:ListItemType.Header: ListItemType.Item: ListItemTyp

创建一个带模版的用户控件 V.2

前面有做练习<创建一个带模版的用户控件>http://www.cnblogs.com/insus/p/4161544.html .过于简化.通常使用数据控件Repeater会有网页写好Header,Item,AlternatingItem和Footer.如果需要动态产生列时,我们需要在后台写好模板. 再来复习一下这篇<Repeater控件动态变更列(Header,Item和Foot)信息>http://www.cnblogs.com/insus/archive/2013/03/22

【WPF学习】第二十章 内容控件

原文:[WPF学习]第二十章 内容控件 内容控件(content control)是更特殊的控件类型,它们可包含并显示一块内容.从技术角度看,内容控件时可以包含单个嵌套元素的控件.与布局容器不同的是,内容控件只能包含一个子元素,而布局容器主要愿意可以包含任意多个牵头元素. 正如前面所介绍,所有WPF布局容器都继承自抽象类Panel,该类提供了对包含多个元素的支持.类似地,所有内容控件都继承自抽象类ContentControl.下图显示了ContentControl类的层次结构. 图 Conten

WPF布局之让你的控件随着窗口等比放大缩小,适应多分辨率满屏填充应用

一直以来,我们设计windows应用程序,都是将控件的尺寸定好,无论窗体大小怎么变,都不会改变,这样的设计对于一般的应用程序来说是没有问题的,但是对于一些比较特殊的应用,比如有背景图片的,需要铺面整个屏幕,由于存在多种不同的分辨率,所以会出现布局混乱的情况.今天我们来看看WPF中如何让我们的控件也随着分辨率放大缩小.下面来写一个例子看看效果吧~  一.普通布局中的问题 这里我们写一个简单的页面,新建WPF项目,在MainWindow里面添加按钮,如下图: 这个页面很简单,只有三个按钮,我们想的是

wpf PNG图形窗体 使用webbrowser控件

wpf ,PNG图形半透明窗体 ,使用webbrowser控件 附件:http://files.cnblogs.com/xe2011/WpfApplication1_webbrowser_transparent.rar MainWindow1.XAML <Window x:Name="MainWindow1" x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.co