基于WPF实现步骤控件的示例代码

WPF 实现步骤控件

框架使用.NET40

Visual Studio 2019;

Step 继承 ItemsControl 使用 Grid 嵌套 ProgressBar 和 ItemsPresenter.

  • ProgressBar 用来当作步骤后面的线条,宽等于控件的(ActualWidth / Items.Count) * (Items.Count - 1),Maximum = Items.Count - 1
  • ItemsPresenter 用来展示步骤 Item 。

ItemsPanel - ItemsPanelTemplate - UniformGrid Rows="1" 横向展示,UniformGrid Columns="1" 可以控制竖向显示,只不过需要重新自定义 ItemContainerStyle 的样式。

然后创建 StepItem 继承 ContentControl 增加两个属性 Index 用来记录当前是步骤 与 State 记录状态 (等待中、进行中、已完成)。

因为继承了 ContentControl 所以可以在使用时指定 Content 显示内容,在每个步骤下方显示。

基于WPF实现步骤控件的示例代码_第1张图片

实现代码

1) Step.xaml 代码如下:


    
        
    

    
    
        
        
            
                
                    
                        
                            
                            
                                
                                    
                                    
                                
                            
                        

                        
                    
                    
                        
                            
                            
                            
                            
                        
                        
                            
                            
                            
                            
                        
                        
                            
                            
                            
                            
                            
                        
                    
                
            
        
    

    
        
        
        
        
            
                
                    
                        
                        
                    
                
            
        
        
            
                
                    
                
            
        
    

    
    

2) Step.cs 代码如下:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace WPFDevelopers.Controls
{
    [TemplatePart(Name = ProgressBarTemplateName, Type = typeof(ProgressBar))]
    public class Step : ItemsControl
    {
        private const string ProgressBarTemplateName = "PART_ProgressBar";
        private ProgressBar _progressBar;
        public int StepIndex
        {
            get => (int)GetValue(StepIndexProperty);
            set => SetValue(StepIndexProperty, value);
        }

        public static readonly DependencyProperty StepIndexProperty = DependencyProperty.Register(
           "StepIndex", typeof(int), typeof(Step), new PropertyMetadata(0, OnStepIndexChanged));

        private static void OnStepIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var step = (Step)d;
            var stepIndex = (int)e.NewValue;
            step.UpdateStepItemState(stepIndex);
        }
        void UpdateStepItemState(int stepIndex)
        {
            var count = Items.Count;
            if (count <= 0) return;
            if (stepIndex >= count)
            {
                StepIndex--;
                return;
            }
            if (stepIndex < 0)
            {
                StepIndex++;
                return;
            }
            for (var i = 0; i < stepIndex; i++)
            {
                if (ItemContainerGenerator.ContainerFromIndex(i) is StepItem stepItem)
                    stepItem.Status = Status.Complete;
            }

            if (ItemContainerGenerator.ContainerFromIndex(stepIndex) is StepItem itemInProgress)
                itemInProgress.Status = Status.InProgress;
            for (var i = stepIndex + 1; i < Items.Count; i++)
            {
                if (ItemContainerGenerator.ContainerFromIndex(i) is StepItem stepItem)
                    stepItem.Status = Status.Waiting;
            }
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _progressBar = GetTemplateChild(ProgressBarTemplateName) as ProgressBar;
        }
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            var count = Items.Count;
            if (_progressBar == null || count <= 0) return;
            _progressBar.Maximum = count - 1;
            _progressBar.Value = StepIndex;
            _progressBar.Width = (ActualWidth / count) * (count - 1);


        }
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is StepItem;
        }
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new StepItem();
        }
        public Step()
        {
            ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
        }

        public void Next()
        {
            StepIndex++;
        }
        public void Previous()
        {
            StepIndex--;
        }
        private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
        {
            if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                var count = Items.Count;
                if (count <= 0) return;
                UpdateStepItemState(StepIndex);
            }
        }
    }
}

3) StepItem.cs 代码如下:

using System.Windows;
using System.Windows.Controls;

namespace WPFDevelopers.Controls
{
    public class StepItem : ContentControl
    {

        public static readonly DependencyProperty IndexProperty = DependencyProperty.Register(
            "Index", typeof(int), typeof(StepItem), new PropertyMetadata(-1));

        public int Index
        {
            get => (int)GetValue(IndexProperty);
            internal set => SetValue(IndexProperty, value);
        }


        public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
            "Status", typeof(Status), typeof(StepItem), new PropertyMetadata(Status.Waiting));


        public Status Status
        {
            get => (Status)GetValue(StatusProperty);
            internal set => SetValue(StatusProperty, value);
        }
    }
}

4) Status.cs 代码如下:

namespace WPFDevelopers.Controls
{
    /// 
    ///状态值
    /// 
    public enum Status
    {
        /// 
        /// 等待中
        /// 
        Waiting,
        /// 
        /// 正在进行中
        /// 
        InProgress,
        /// 
        /// 完成
        /// 
        Complete
    }
}

5) StepExample.xaml 代码如下:


    
        
            
                
                    
                    
                    
                    
                
                
                
            
            
                
                
               
            
            
        
        
            
            
        
    

6) StepExample.xaml.cs 代码如下:

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using WPFDevelopers.Controls;
using WPFDevelopers.Samples.Helpers;

namespace WPFDevelopers.Samples.ExampleViews
{
    /// 
    /// StepExample.xaml 的交互逻辑
    /// 
    public partial class StepExample : UserControl
    {
        public ObservableCollection Steps
        {
            get;
            set;
        }
        public StepExample()
        {
            InitializeComponent();
            Steps = new ObservableCollection();
            Steps.Add("Step 1");
            Steps.Add("Step 2");
            Steps.Add("Step 3");
            Steps.Add("Step 4");
            this.DataContext = this;
        }
        public ICommand NextCommand => new RelayCommand(new Action((sender) =>
        {
            var uniformGrid = sender as UniformGrid;
            if (uniformGrid == null) return;
            foreach (var step in uniformGrid.Children.OfType())
                step.Next();

        }));
        public ICommand PreviousCommand => new RelayCommand(new Action((sender) =>
        {
            var uniformGrid = sender as UniformGrid;
            if (uniformGrid == null) return;
            foreach (var step in uniformGrid.Children.OfType())
                step.Previous();
        }));
    }
} 
  
 

效果图

基于WPF实现步骤控件的示例代码_第2张图片

以上就是基于WPF实现步骤控件的示例代码的详细内容,更多关于WPF步骤控件的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(基于WPF实现步骤控件的示例代码)