125 lines
5.2 KiB
C#
125 lines
5.2 KiB
C#
|
|
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
|
|||
|
|
}
|