16WPF---用户控件

用户控件UserControl标签可以被包含,而Window只能是顶级控件,不能被包含。

 有些主题

xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2">在Win7下不可用

FileNameWindows Theme
Classic.xamlClassic Windows 9x/2000 look on Windows XP
Luna.NormalColor.xmalDefault blue theme on Windows XP
Luna.Homestead.xmalOlive them on Windows XP
Luna.Metail.xmalSilver theme on Windows XP
Royal.NormalColor.xmalDefault them on Windows XP
Aero.NormalColor.xmalDefault theme on Windows Visa/Windows 7 

实现效果:

 UI代码:

<UserControl x:Class="WPF控件实例.Instrument"
             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:WPF控件实例"
             mc:Ignorable="d" 
             d:DesignHeight="400" d:DesignWidth="400">
    <Grid>
        <Border Name="border" Background="#FF030A28">
            <Border.Effect>
                <DropShadowEffect BlurRadius="20" Opacity="0.5"  ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/>
            </Border.Effect>
            <Grid>
                <Path Stroke="#333CAFFF" StrokeThickness="10" Name="circle" RenderTransformOrigin="0.5,0.5">
                    <Path.RenderTransform>
                        <RotateTransform Angle="-45"/>
                    </Path.RenderTransform>
                </Path>
                
                <Canvas x:Name="canvasPlate" RenderTransformOrigin="0.5,0.5" Margin="0">
                    <Canvas.RenderTransform>
                        <RotateTransform Angle="-45"/>
                    </Canvas.RenderTransform>
                </Canvas>
                
                <Path Data="" Name="plateBorder" Stroke="#FF3CAFFF" StrokeThickness="3" RenderTransformOrigin="0.5,0.5"
                      Width="{Binding ElementName=border,Path=Width}"
                      Height="{Binding ElementName=border,Path=Height}">
                    <Path.RenderTransform>
                        <RotateTransform Angle="-45"/>
                    </Path.RenderTransform>
                </Path>
                
                <Path Data="M200 205,360 200,200 195,195 200 200 205" Fill="Red" RenderTransformOrigin="0.5,0.5" Name="pointer">
                    <Path.RenderTransform>
                        <RotateTransform Angle="135" x:Name="rtPointer"/>
                    </Path.RenderTransform>
                </Path>
                
                <Border Width="60" Height="60" CornerRadius="30" Background="#FF030A28">
                    <Border.Effect>
                        <DropShadowEffect BlurRadius="20" Opacity="0.3" ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/>
                    </Border.Effect>
                    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
                        <TextBlock Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center">
                            <Run Text="{Binding Value,RelativeSource={RelativeSource AncestorType=UserControl}}"
                                 FontSize="20"/>
                            <Run Text="m³/H" FontSize="8"/>
                        </TextBlock>
                        <TextBlock Text="NATURAL GAS" Foreground="#FF8CBEF0" VerticalAlignment="Center" HorizontalAlignment="Center"
                                   FontSize="6"/>
                    </StackPanel>
                </Border>
            </Grid>
        </Border>
    </Grid>
</UserControl>

逻辑代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 WPF控件实例
{
    /// <summary>
    /// Instrument.xaml 的交互逻辑
    /// </summary>
    public partial class Instrument : UserControl
    {
        public Instrument()
        {
            InitializeComponent();
        }
        // 当前值 
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));

        // 最小刻度
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));

        // 最大刻度
        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));

        // 间隔
        public double Interval
        {
            get { return (double)GetValue(IntervalProperty); }
            set { SetValue(IntervalProperty, value); }
        }
        public static readonly DependencyProperty IntervalProperty =
            DependencyProperty.Register("Interval", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));

        // 大刻度的个数
        public int ScaleCount
        {
            get { return (int)GetValue(ScaleCountProperty); }
            set { SetValue(ScaleCountProperty, value); }
        }
        public static readonly DependencyProperty ScaleCountProperty =
            DependencyProperty.Register("ScaleCount", typeof(int), typeof(Instrument), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged)));

        // 刻度的厚度
        public double ScaleThickness
        {
            get { return (double)GetValue(ScaleThicknessProperty); }
            set { SetValue(ScaleThicknessProperty, value); }
        }
        public static readonly DependencyProperty ScaleThicknessProperty =
            DependencyProperty.Register("ScaleThickness", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged)));
        // 刻度的颜色
        public Brush ScaleBrush
        {
            get { return (Brush)GetValue(ScaleBrushProperty); }
            set { SetValue(ScaleBrushProperty, value); }
        }
        public static readonly DependencyProperty ScaleBrushProperty =
            DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged)));

        // 指针的颜色
        public Brush PointerBrush
        {
            get { return (Brush)GetValue(PointerBrushProperty); }
            set { SetValue(PointerBrushProperty, value); }
        }
        public static readonly DependencyProperty PointerBrushProperty =
            DependencyProperty.Register("PointerBrush", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged)));

        // 刻度字体大小 
        public new double FontSize
        {
            get { return (double)GetValue(FontSizeProperty); }
            set { SetValue(FontSizeProperty, value); }
        }
        public static new readonly DependencyProperty FontSizeProperty =
            DependencyProperty.Register("FontSize", typeof(double), typeof(Instrument), new PropertyMetadata(9.0, new PropertyChangedCallback(OnPropertyChanged)));
        
       public static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as Instrument).Refresh();
        }

        private void Refresh()
        {
            // 圆
            this.border.Width = Math.Min(RenderSize.Width, RenderSize.Height);
            this.border.Height = Math.Min(RenderSize.Width, RenderSize.Height);
            this.border.CornerRadius = new CornerRadius(this.border.Width / 2);
            // 半径
            double radius = this.border.Width / 2;

            this.canvasPlate.Children.Clear();
            if (ScaleCount <= 0 || radius <= 0) return;

            // 画边
            string borderPathData = $"M4,{radius}A{radius - 4} {radius - 4} 0 1 1 {radius} {this.border.Height - 4}";
            // 将字符串转换成Geometry
            var converter = TypeDescriptor.GetConverter(typeof(Geometry));
            this.plateBorder.Data = (Geometry)converter.ConvertFrom(borderPathData);


            // 计算刻度
            double label = this.Minimum;
            double interval = 0;
            double step = 270.0 / (this.Maximum - this.Minimum);

            // 计算小刻度
            for (int i = 0; i < this.Maximum - this.Minimum; i++)
            {
                //添加刻度线
                Line lineScale = new Line();
                // 角度需要转换弧度
                lineScale.X1 = radius - (radius - 13) * Math.Cos(step * i * Math.PI / 180);
                lineScale.Y1 = radius - (radius - 13) * Math.Sin(step * i * Math.PI / 180);
                lineScale.X2 = radius - (radius - 8) * Math.Cos(step * i * Math.PI / 180);
                lineScale.Y2 = radius - (radius - 8) * Math.Sin(step * i * Math.PI / 180);

                lineScale.Stroke = this.ScaleBrush;
                lineScale.StrokeThickness = this.ScaleThickness;

                this.canvasPlate.Children.Add(lineScale);
            }
            // 计算大刻度
            do
            {
                //添加刻度线
                Line lineScale = new Line();
                lineScale.X1 = radius - (radius - 20) * Math.Cos(interval * step * Math.PI / 180);
                lineScale.Y1 = radius - (radius - 20) * Math.Sin(interval * step * Math.PI / 180);
                lineScale.X2 = radius - (radius - 8) * Math.Cos(interval * step * Math.PI / 180);
                lineScale.Y2 = radius - (radius - 8) * Math.Sin(interval * step * Math.PI / 180);

                lineScale.Stroke = this.ScaleBrush;
                lineScale.StrokeThickness = this.ScaleThickness;

                this.canvasPlate.Children.Add(lineScale);

                TextBlock txtScale = new TextBlock();
                txtScale.Text = label.ToString("0");
                txtScale.Width = 34;
                txtScale.TextAlignment = TextAlignment.Center;
                txtScale.Foreground = new SolidColorBrush(Colors.White);
                txtScale.RenderTransform = new RotateTransform() { Angle = 45, CenterX = 17, CenterY = 8 };
                txtScale.FontSize = this.FontSize;
                Canvas.SetLeft(txtScale, radius - (radius - 34) * Math.Cos(interval * step * Math.PI / 180) - 17);
                Canvas.SetTop(txtScale, radius - (radius - 34) * Math.Sin(interval * step * Math.PI / 180) - 8);
                this.canvasPlate.Children.Add(txtScale);

                interval += (this.Maximum - this.Minimum) / this.ScaleCount;
                label += (this.Maximum - this.Minimum) / this.ScaleCount;

            } while (interval <= this.Maximum - this.Minimum);


            // 修改指针
            string sData = "M{0} {1},{2} {0},{0} {3},{3} {0},{0} {1}";
            sData = string.Format(sData, radius, radius + 2, this.border.Width - radius / 10, radius - 4);
            converter = TypeDescriptor.GetConverter(typeof(Geometry));
            this.pointer.Data = (Geometry)converter.ConvertFrom(sData);
            this.pointer.Fill = this.PointerBrush;

            //DoubleAnimation da = new DoubleAnimation((Value - Minimum) * step + 135, new Duration(TimeSpan.FromMilliseconds(200)));
            //this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da);
            this.rtPointer.Angle = (Value - Minimum) * step + 135;

            // 修改圆  M100 200 A100 100 0 1 1 200 300
            // 厚度
            double thickness = radius / 2;
            this.circle.StrokeThickness = thickness;
            double startX = radius - thickness / 2;
            double startY = radius;
            double endX = radius - (radius - thickness / 2) * Math.Cos((Value - Minimum) * step * Math.PI / 180);
            double endY = radius - (radius - thickness / 2) * Math.Sin((Value - Minimum) * step * Math.PI / 180);

            int isLarge = 1;
            if ((Value - Minimum) * step < 180)
                isLarge = 0;

            sData = $"M{startX},{startY}A{radius / 2} {radius / 2} 0 1 1 {endX} {endY}";
            sData = $"M{thickness / 2},{radius}A{radius - thickness / 2} {radius - thickness / 2} 0 {isLarge} 1 {endX} {endY}";
            //sData = string.Format(sData, radius * 0.5, radius, radius * 1.5);
            this.circle.Data = (Geometry)converter.ConvertFrom(sData);
            this.circle.Visibility = Visibility.Visible;

            if (this.border.Width < 200)
                this.circle.Visibility = Visibility.Collapsed;
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值