文章出處

在設計界面時,有時會遇到進度條,本次講解如何設計自定義的繞圈進度條,直接上代碼:

 

1、控件界面

<UserControl x:Class="ProgressBarControl" 
             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"
             mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="300"
             Background="Gray" Loaded="ProgressBarControl_OnLoaded">

    <Grid>
        <Grid.Resources>
            <Style TargetType="Ellipse">
                <Setter Property="Height" Value="{Binding EclipseSize}"></Setter>
                <Setter Property="Width" Value="{Binding EclipseSize}"></Setter>
                <Setter Property="Stretch" Value="Fill"></Setter>
                <!--設置圓的顏色-->
                <Setter Property="Fill" Value="White"></Setter>
            </Style>
        </Grid.Resources>
        <StackPanel   HorizontalAlignment="Center"  
            VerticalAlignment="Center">
            <Viewbox Width="{Binding ViewBoxSize}" Height="{Binding ViewBoxSize}"  
            HorizontalAlignment="Center"  
            VerticalAlignment="Center">
                <Grid x:Name="LayoutRoot"   
                Background="Transparent"  
                HorizontalAlignment="Center"  
                VerticalAlignment="Center">
                    <!--此處有canvas的加載和卸載事件-->
                    <Canvas x:Name="ProgressBarCanvas" RenderTransformOrigin="0.5,0.5"  
                    HorizontalAlignment="Center"  
                    VerticalAlignment="Center" Width="{Binding CanvasSize}"  
                    Height="{Binding CanvasSize}" Loaded="HandleLoaded"  
                    Unloaded="HandleUnloaded"  >
                        <!--畫圓-->                        
                        <Canvas.RenderTransform>
                            <RotateTransform x:Name="SpinnerRotate" Angle="0" />
                        </Canvas.RenderTransform>
                    </Canvas>
                </Grid>
            </Viewbox>
        </StackPanel>
    </Grid>
</UserControl> 

 

2、控件后臺邏輯:

 控件后臺:

/// <summary>
    /// 進度條
    /// </summary>
    public partial class ProgressBarControl : UserControl
    {
        //集成到按指定時間間隔和指定優先級處理的 System.Windows.Threading.Dispatcher 隊列中的計時器。
        private DispatcherTimer animationTimer;
        private ProgressBarDataModel _dataModel;
        private int index = 0;
        #region 構造方法與加載
        /// <summary>
        /// 構造方法
        /// </summary>
        public ProgressBarControl()
        {
            InitializeComponent();
            
        }
        /// <summary>
        /// 加載后刷新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressBarControl_OnLoaded(object sender, RoutedEventArgs e)
        {
            animationTimer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher);
            //指定時間間隔
            animationTimer.Interval = new TimeSpan(0, 0, 0, 0, TimeSpan);
            if (EllipseCount < 1)
            {
                EllipseCount = 12;
            }
            for (int i = 0; i < EllipseCount; i++)
            {
                ProgressBarCanvas.Children.Add(new Ellipse());
            }
            var dataModel = new ProgressBarDataModel()
            {
                CanvasSize = CanvasSize,
                EclipseSize = EllipseSize
            };
            _dataModel = dataModel;
            this.DataContext = dataModel;
        }
        #endregion

        #region 屬性
        /// <summary>
        /// 獲取或設置圓圈數量
        /// 默認12
        /// </summary>
        public double EllipseCount
        {
            get { return (double)GetValue(EllipseCountProperty); }
            set { SetValue(EllipseCountProperty, value); }
        }
        public static readonly DependencyProperty EllipseCountProperty =
            DependencyProperty.Register("EllipseCount", typeof(double), typeof(ProgressBarControl),
            new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));

        /// <summary>
        /// 獲取或設置圓圈大小
        /// 默認10
        /// </summary>
        public double EllipseSize
        {
            get { return (double)GetValue(EllipseSizeProperty); }
            set { SetValue(EllipseSizeProperty, value); }
        }
        public static readonly DependencyProperty EllipseSizeProperty =
            DependencyProperty.Register("EllipseSize", typeof(double), typeof(ProgressBarControl),
            new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));

        /// <summary>
        /// 獲取或設置面板大小
        /// 默認80
        /// </summary>
        public double CanvasSize
        {
            get { return (double)GetValue(CanvasSizeProperty); }
            set { SetValue(CanvasSizeProperty, value); }
        }
        public static readonly DependencyProperty CanvasSizeProperty =
            DependencyProperty.Register("CanvasSize", typeof(double), typeof(ProgressBarControl),
            new FrameworkPropertyMetadata(80.0, FrameworkPropertyMetadataOptions.AffectsRender));

        /// <summary>
        /// 獲取或設置每次旋轉角度
        /// 默認10.0
        /// </summary>
        public double StepAngle
        {
            get { return (double)GetValue(StepAngleProperty); }
            set { SetValue(StepAngleProperty, value); }
        }

        public static readonly DependencyProperty StepAngleProperty =
            DependencyProperty.Register("StepAngle", typeof(double), typeof(ProgressBarControl),
            new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
        /// <summary>
        /// 獲取或設置每次旋轉間隔時間(毫秒)
        /// 默認100毫秒
        /// </summary>
        public int TimeSpan
        {
            get { return (int)GetValue(TimeSpanProperty); }
            set { SetValue(TimeSpanProperty, value); }
        }
        public static readonly DependencyProperty TimeSpanProperty =
            DependencyProperty.Register("TimeSpan", typeof(int), typeof(ProgressBarControl),
            new FrameworkPropertyMetadata(100, FrameworkPropertyMetadataOptions.AffectsRender));
       
        #endregion

        #region 方法
        /// <summary>
        /// Canvas加載
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleLoaded(object sender, RoutedEventArgs e)
        {
            //設置設置圓的位置和旋轉角度
            SetEclipsePosition(_dataModel);
            //DesignerProperties   提供用于與設計器進行通信的附加屬性。
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                if (this.Visibility == System.Windows.Visibility.Visible)
                {
                    //超過計時器間隔時發生。
                    animationTimer.Tick += HandleAnimationTick;
                    animationTimer.Start();
                }
            }
        }

        /// <summary>
        /// 設置圓的位置和旋轉角度
        /// </summary>
        private void SetEclipsePosition(ProgressBarDataModel dataModel)
        {
            //圓周長就是:C = π * d 或者C=2*π*r(其中d是圓的直徑,r是圓的半徑)
            double r =dataModel.R;

            var children=ProgressBarCanvas.Children;
            int count = children.Count;
            double step = (Math.PI * 2) / count;

            //根據圓中正弦、余弦計算距離
            int index = 0;
            foreach (var element in children)
            {
                var ellipse = element as Ellipse;
                //透明度
                var opacity = Convert.ToDouble(index)/(count - 1);
                ellipse.SetValue(UIElement.OpacityProperty, opacity<0.05?0.05:opacity);
                //距離
                double left = r + Math.Sin(step*index)*r;
                ellipse.SetValue(Canvas.LeftProperty,left);
                double top = r - Math.Cos(step*index)*r;
                ellipse.SetValue(Canvas.TopProperty, top);

                index++;
            }
        }

        /// <summary>
        /// Canvas卸載時
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleUnloaded(object sender, RoutedEventArgs e)
        {
            animationTimer.Stop();
            //除去委托
            animationTimer.Tick -= HandleAnimationTick;
        }

        /// <summary>
        /// 超過計時器間隔時發生。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleAnimationTick(object sender, EventArgs e)
        {
            //設置旋轉角度
            SpinnerRotate.Angle = (SpinnerRotate.Angle + StepAngle) % 360;
        }
        #endregion
    }
View Code

數據Model類: 

/// <summary>
    /// 進度條Model類
    /// </summary>
    public class ProgressBarDataModel
    {
        public double EclipseSize { get; set; }
        public double CanvasSize { get; set; }
        public double ViewBoxSize
        {
            get
            {
                double length = Convert.ToDouble(CanvasSize) - Convert.ToDouble(EclipseSize);
                return length;
            }
        }
        public double EclipseLeftLength
        {
            get
            {
                double length = Convert.ToDouble(CanvasSize) / 2;
                return length;
            }
        }
        public double R
        {
            get
            {
                double length = (Convert.ToDouble(CanvasSize) - Convert.ToDouble(EclipseSize)) / 2;
                return length;
            }
        }
    }

 

 

3、取用控件

<control:ProgressBarControl  CanvasSize="100" EllipseCount="9" EllipseSize="10" StepAngle="10" TimeSpan="200"></control:ProgressBarControl>

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()