Files
Shrlalgo.RvKits/Melskin/Controls/StepBar.xaml.cs

125 lines
5.2 KiB
C#
Raw Normal View History

2026-02-22 20:03:42 +08:00
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
}