using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace Melskin.Controls { public class StepBar : ItemsControl { // 使用 StepProgress 代替 SelectedIndex,允许值范围 0 到 Items.Count public static readonly DependencyProperty StepProgressProperty = DependencyProperty.Register("StepProgress", typeof(int), typeof(StepBar), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnStepProgressChanged)); public int StepProgress { get => (int)GetValue(StepProgressProperty); set => SetValue(StepProgressProperty, value); } public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(StepBar), new PropertyMetadata(Orientation.Horizontal)); public Orientation Orientation { get => (Orientation)GetValue(OrientationProperty); set => SetValue(OrientationProperty, value); } static StepBar() { DefaultStyleKeyProperty.OverrideMetadata(typeof(StepBar), new FrameworkPropertyMetadata(typeof(StepBar))); } private static void OnStepProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is StepBar bar) bar.UpdateItemsStatus(); } protected override DependencyObject GetContainerForItemOverride() => new StepBarItem(); protected override bool IsItemItsOwnContainerOverride(object item) => item is StepBarItem; protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); UpdateItemsStatus(); } internal void UpdateItemsStatus() { for (int i = 0; i < Items.Count; i++) { if (ItemContainerGenerator.ContainerFromIndex(i) is StepBarItem container) { container.Index = i + 1; container.IsLast = (i == Items.Count - 1); container.Orientation = this.Orientation; // 核心逻辑: // i < Progress -> 已完成 (Completed) // i == Progress -> 进行中 (Active) // i > Progress -> 等待 (Waiting) if (i < StepProgress) container.Status = StepStatus.Completed; else if (i == StepProgress) container.Status = StepStatus.Active; else container.Status = StepStatus.Waiting; } } } } public class StepBarItem : ContentControl { public static readonly DependencyProperty StatusProperty = DependencyProperty.Register("Status", typeof(StepStatus), typeof(StepBarItem), new PropertyMetadata(StepStatus.Waiting)); public StepStatus Status { get => (StepStatus)GetValue(StatusProperty); set => SetValue(StatusProperty, value); } public static readonly DependencyProperty IndexProperty = DependencyProperty.Register("Index", typeof(int), typeof(StepBarItem), new PropertyMetadata(1)); public int Index { get => (int)GetValue(IndexProperty); set => SetValue(IndexProperty, value); } public static readonly DependencyProperty IsLastProperty = DependencyProperty.Register("IsLast", typeof(bool), typeof(StepBarItem), new PropertyMetadata(false)); public bool IsLast { get => (bool)GetValue(IsLastProperty); set => SetValue(IsLastProperty, value); } public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(StepBarItem), new PropertyMetadata(Orientation.Horizontal)); public Orientation Orientation { get => (Orientation)GetValue(OrientationProperty); set => SetValue(OrientationProperty, value); } static StepBarItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(StepBarItem), new FrameworkPropertyMetadata(typeof(StepBarItem))); } protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); var parent = ItemsControl.ItemsControlFromItemContainer(this) as StepBar; if (parent != null) { int myIndex = parent.ItemContainerGenerator.IndexFromContainer(this); // 点击逻辑: // 1. 如果点的是当前正在进行的步 -> 完成这一步,进度+1 // 2. 如果点的是已经完成的步 -> 回退到那一步 // 3. 如果点的是还没开始的步 -> 直接跳到那一步 if (parent.StepProgress == myIndex) { parent.StepProgress = myIndex + 1; } else { parent.StepProgress = myIndex; } } } } } public enum StepStatus { Completed, Active, Waiting }