2025-08-12 23:08:54 +08:00
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
|
|
2026-01-02 17:30:41 +08:00
|
|
|
|
namespace Melskin.Controls;
|
2025-08-12 23:08:54 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 面包屑
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(BreadcrumbItem))]
|
|
|
|
|
|
public class Breadcrumb : ItemsControl
|
|
|
|
|
|
{
|
|
|
|
|
|
#region 事件
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导航
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly RoutedEvent NavigateEvent = EventManager.RegisterRoutedEvent(
|
|
|
|
|
|
"Navigate",
|
|
|
|
|
|
RoutingStrategy.Direct,
|
|
|
|
|
|
typeof(RoutedPropertyChangedEventHandler<string>),
|
|
|
|
|
|
typeof(Breadcrumb));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导航
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event RoutedPropertyChangedEventHandler<string> Navigate
|
|
|
|
|
|
{
|
|
|
|
|
|
add => AddHandler(NavigateEvent, value);
|
|
|
|
|
|
remove => RemoveHandler(NavigateEvent, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 属性
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 链接
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty HrefProperty =
|
|
|
|
|
|
DependencyProperty.Register(
|
|
|
|
|
|
nameof(Href),
|
|
|
|
|
|
typeof(string),
|
|
|
|
|
|
typeof(Breadcrumb),
|
|
|
|
|
|
new FrameworkPropertyMetadata(string.Empty));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 链接
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string Href { get => (string)GetValue(HrefProperty);
|
|
|
|
|
|
set => SetValue(HrefProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty SeparatorProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Separator), typeof(string), typeof(Breadcrumb), new FrameworkPropertyMetadata("/"));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string Separator
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (string)GetValue(SeparatorProperty);
|
|
|
|
|
|
set => SetValue(SeparatorProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符颜色
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty SeparatorBrushProperty =
|
|
|
|
|
|
DependencyProperty.Register(
|
|
|
|
|
|
nameof(SeparatorBrush),
|
|
|
|
|
|
typeof(Brush),
|
|
|
|
|
|
typeof(Breadcrumb),
|
|
|
|
|
|
new FrameworkPropertyMetadata(null));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符颜色
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Brush SeparatorBrush
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (Brush)GetValue(SeparatorBrushProperty);
|
|
|
|
|
|
set => SetValue(SeparatorBrushProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
static Breadcrumb()
|
|
|
|
|
|
{ DefaultStyleKeyProperty.OverrideMetadata(typeof(Breadcrumb), new FrameworkPropertyMetadata(typeof(Breadcrumb))); }
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
protected override bool IsItemItsOwnContainerOverride(object item) { return item is BreadcrumbItem; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
protected override DependencyObject GetContainerForItemOverride() { return new BreadcrumbItem(); }
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
public override void OnApplyTemplate()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnApplyTemplate();
|
|
|
|
|
|
|
|
|
|
|
|
Loaded += Breadcrumb_Loaded;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Breadcrumb_Loaded(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Loaded -= Breadcrumb_Loaded;
|
|
|
|
|
|
|
|
|
|
|
|
for(var i = 0; i < Items.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(ItemContainerGenerator.ContainerFromIndex(i) is BreadcrumbItem breadcrumbItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
breadcrumbItem.Navigate += BreadcrumbItem_Navigate;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnItemsChanged(e);
|
|
|
|
|
|
|
2026-01-02 16:37:37 +08:00
|
|
|
|
if (e.OldItems is null) return;
|
|
|
|
|
|
if (e.NewItems != null)
|
2025-08-12 23:08:54 +08:00
|
|
|
|
{
|
2026-01-02 16:37:37 +08:00
|
|
|
|
foreach (var item in e.NewItems.OfType<BreadcrumbItem>())
|
2025-08-12 23:08:54 +08:00
|
|
|
|
{
|
|
|
|
|
|
item.Navigate += BreadcrumbItem_Navigate;
|
|
|
|
|
|
}
|
2026-01-02 16:37:37 +08:00
|
|
|
|
}
|
2025-08-12 23:08:54 +08:00
|
|
|
|
|
2026-01-02 16:37:37 +08:00
|
|
|
|
foreach(var item in e.OldItems.OfType<BreadcrumbItem>())
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Navigate -= BreadcrumbItem_Navigate;
|
2025-08-12 23:08:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void BreadcrumbItem_Navigate(object sender, RoutedPropertyChangedEventArgs<string> e)
|
|
|
|
|
|
{
|
|
|
|
|
|
RaiseEvent(new RoutedPropertyChangedEventArgs<string>(Href, e.NewValue) { RoutedEvent = NavigateEvent });
|
|
|
|
|
|
|
|
|
|
|
|
Href = e.NewValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 面包屑子项
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class BreadcrumbItem : Button
|
|
|
|
|
|
{
|
|
|
|
|
|
static BreadcrumbItem()
|
|
|
|
|
|
{
|
|
|
|
|
|
DefaultStyleKeyProperty.OverrideMetadata(
|
|
|
|
|
|
typeof(BreadcrumbItem),
|
|
|
|
|
|
new FrameworkPropertyMetadata(typeof(BreadcrumbItem)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region 事件
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导航
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly RoutedEvent NavigateEvent = EventManager.RegisterRoutedEvent(
|
|
|
|
|
|
"Navigate",
|
|
|
|
|
|
RoutingStrategy.Direct,
|
|
|
|
|
|
typeof(RoutedPropertyChangedEventHandler<string>),
|
|
|
|
|
|
typeof(BreadcrumbItem));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导航
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event RoutedPropertyChangedEventHandler<string> Navigate
|
|
|
|
|
|
{
|
|
|
|
|
|
add => AddHandler(NavigateEvent, value);
|
|
|
|
|
|
remove => RemoveHandler(NavigateEvent, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 属性
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 链接
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty HrefProperty =
|
|
|
|
|
|
DependencyProperty.Register(
|
|
|
|
|
|
nameof(Href),
|
|
|
|
|
|
typeof(string),
|
|
|
|
|
|
typeof(BreadcrumbItem),
|
|
|
|
|
|
new FrameworkPropertyMetadata(string.Empty));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 链接
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string Href
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (string)GetValue(HrefProperty);
|
|
|
|
|
|
set => SetValue(HrefProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty SeparatorProperty =
|
|
|
|
|
|
DependencyProperty.Register(
|
|
|
|
|
|
nameof(Separator),
|
|
|
|
|
|
typeof(string),
|
|
|
|
|
|
typeof(BreadcrumbItem),
|
|
|
|
|
|
new FrameworkPropertyMetadata("/"));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string Separator
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (string)GetValue(SeparatorProperty);
|
|
|
|
|
|
set => SetValue(SeparatorProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符颜色
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty SeparatorBrushProperty =
|
|
|
|
|
|
DependencyProperty.Register(
|
|
|
|
|
|
nameof(SeparatorBrush),
|
|
|
|
|
|
typeof(Brush),
|
|
|
|
|
|
typeof(BreadcrumbItem),
|
|
|
|
|
|
new FrameworkPropertyMetadata(null));
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分隔符颜色
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Brush SeparatorBrush
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (Brush)GetValue(SeparatorBrushProperty);
|
|
|
|
|
|
set => SetValue(SeparatorBrushProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
protected override void OnClick()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnClick();
|
|
|
|
|
|
|
2025-08-20 12:10:35 +08:00
|
|
|
|
RaiseEvent(new RoutedPropertyChangedEventArgs<string?>(null, Href) { RoutedEvent = NavigateEvent });
|
2025-08-12 23:08:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|