基于WPF实现面包屑控件的示例代码
作者:WPF开发者 发布时间:2021-12-19 12:34:33
标签:WPF,面包屑,控件
WPF 实现面包屑控件
框架使用
.NET4 至 .NET6
Visual Studio 2022
创建
BreadCrumbBar.xaml
设置VirtualizingStackPanel
为水平方向显示Orientation="Horizontal"
。创建
BreadCrumbBarItem.xaml
设置ContentPresenter
前显示符号>
,通过BreadCrumbBarConvertr
转换器判断如果是当前是第0
个则隐藏显示符>
。创建
BreadCrumbBar.cs
继承ListBox
当选中时获取当前的SelectedIndex
大于当前的设置IsEnabled
设置false
反之则为true
。
实现代码
1)创建 BreadCrumbBar.cs
代码如下:
using System.Collections;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
namespace WPFDevelopers.Controls
{
public class BreadCrumbBar : ListBox
{
static BreadCrumbBar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BreadCrumbBar), new FrameworkPropertyMetadata(typeof(BreadCrumbBar)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
for (int i = 0; i <= SelectedIndex; i++)
{
var item = (ListBoxItem)ItemContainerGenerator.ContainerFromIndex(i);
if (item == null) continue;
if (!item.IsEnabled)
item.IsEnabled = true;
}
for (int i = Items.Count - 1; i > SelectedIndex; i--)
{
var item = (ListBoxItem)ItemContainerGenerator.ContainerFromIndex(i);
if (item == null) continue;
if(item.IsEnabled)
item.IsEnabled = false;
}
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is BreadCrumbBarItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return new BreadCrumbBarItem();
}
}
}
2)创建 BreadCrumbBarItem.cs
代码如下:
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFDevelopers.Controls
{
public class BreadCrumbBarItem : ListBoxItem
{
private static readonly Type _typeofSelf = typeof(BreadCrumbBarItem);
static BreadCrumbBarItem()
{
DefaultStyleKeyProperty.OverrideMetadata(_typeofSelf,
new FrameworkPropertyMetadata(_typeofSelf));
}
}
}
3)创建 BreadCrumbBar.xaml
代码如下:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WPFDevelopers.Controls"
xmlns:converts="clr-namespace:WPFDevelopers.Converts">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Basic/ControlBasic.xaml" />
</ResourceDictionary.MergedDictionaries>
<converts:BreadCrumbBarConvertr x:Key="WD.BreadCrumbBarConvertr" />
<Style
x:Key="WD.BreadCrumbBarItem"
BasedOn="{StaticResource WD.ControlBasicStyle}"
TargetType="{x:Type controls:BreadCrumbBarItem}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="6,0" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="FontSize" Value="{StaticResource WD.TitleFontSize}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:BreadCrumbBarItem}">
<StackPanel Orientation="Horizontal">
<Path
Name="PART_PathSymbol"
Width="9"
Height="9"
Data="{StaticResource WD.BreadCrumbBarGeometry}"
Fill="{DynamicResource WD.PlaceholderTextSolidColorBrush}"
IsHitTestVisible="False"
Stretch="Uniform">
<Path.Visibility>
<MultiBinding Converter="{StaticResource WD.BreadCrumbBarConvertr}">
<Binding RelativeSource="{RelativeSource AncestorType=ListBoxItem}" />
<Binding Path="SelectedIndex" RelativeSource="{RelativeSource AncestorType=ListBox}" />
</MultiBinding>
</Path.Visibility>
</Path>
<ContentPresenter
x:Name="PART_ContentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
TextElement.Foreground="{TemplateBinding Foreground}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource WD.PrimaryMouseOverSolidColorBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="WD.BreadCrumbBar"
BasedOn="{StaticResource WD.ControlBasicStyle}"
TargetType="{x:Type controls:BreadCrumbBar}">
<Setter Property="Height" Value="40" />
<Setter Property="Margin" Value="5" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle" Value="{StaticResource WD.BreadCrumbBarItem}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:BreadCrumbBar}">
<Border
Margin="{TemplateBinding Margin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Auto">
<ItemsPresenter x:Name="ItemsHost" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource WD.BreadCrumbBar}" TargetType="{x:Type controls:BreadCrumbBar}" />
</ResourceDictionary>
4)创建 BreadCrumbBarConverter.cs
代码如下:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WPFDevelopers.Converts
{
public class BreadCrumbBarConvertr : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var item = values[0] as ListBoxItem;
var listBox = ItemsControl.ItemsControlFromItemContainer(item) as ListBox;
if (listBox == null) return Visibility.Collapsed;
var arrayIndex = listBox.ItemContainerGenerator.IndexFromContainer(item);
if (arrayIndex == 0)
return Visibility.Collapsed;
return Visibility.Visible;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
5)创建 BreadCrumbBarExample.xaml
代码如下:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<wd:BreadCrumbBar
DisplayMemberPath="Text"
ItemsSource="{Binding BreadcrumbItems, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding BreadcrumbItem, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectionChanged="BreadCrumbBar_SelectionChanged" />
<Frame
Name="myFrame"
Grid.Row="1"
NavigationUIVisibility="Hidden" />
<Button
Grid.Row="2"
Width="80"
Click="btnNext_Click"
Content="Next"
Style="{StaticResource WD.SuccessPrimaryButton}" />
</Grid>
6) BreadCrumbBarExample.xaml.cs
代码如下:
using System.Collections.Generic;
using System;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Windows;
using System.Reflection;
namespace WPFDevelopers.Samples.ExampleViews
{
/// <summary>
/// StepExample.xaml 的交互逻辑
/// </summary>
public partial class BreadCrumbBarExample : UserControl
{
private int index = 0;
private List<BreadcrumbItem> Breadcrumbs = new List<BreadcrumbItem>();
public ObservableCollection<BreadcrumbItem> BreadcrumbItems
{
get { return (ObservableCollection<BreadcrumbItem>)GetValue(BreadcrumbItemsProperty); }
set { SetValue(BreadcrumbItemsProperty, value); }
}
public static readonly DependencyProperty BreadcrumbItemsProperty =
DependencyProperty.Register("BreadcrumbItems", typeof(ObservableCollection<BreadcrumbItem>), typeof(BreadCrumbBarExample), new PropertyMetadata(null));
public BreadcrumbItem BreadcrumbItem
{
get { return (BreadcrumbItem)GetValue(BreadcrumbItemProperty); }
set { SetValue(BreadcrumbItemProperty, value); }
}
public static readonly DependencyProperty BreadcrumbItemProperty =
DependencyProperty.Register("BreadcrumbItem", typeof(BreadcrumbItem), typeof(BreadCrumbBarExample), new PropertyMetadata(null));
public BreadCrumbBarExample()
{
InitializeComponent();
Loaded += BreadCrumbBarExample_Loaded;
}
private void BreadCrumbBarExample_Loaded(object sender, RoutedEventArgs e)
{
var breadcrumbItems = new List<BreadcrumbItem>()
{
new BreadcrumbItem() { Text = "主页" , Uri=new Uri("pack://application:,,,/WPFDevelopers.Samples;component/ExampleViews/DrawerMenu/HomePage.xaml",UriKind.Absolute ) },
new BreadcrumbItem() { Text = "Edge", Uri=new Uri("pack://application:,,,/WPFDevelopers.Samples;component/ExampleViews/DrawerMenu/EdgePage.xaml" ,UriKind.Absolute ) },
new BreadcrumbItem() { Text = "邮件", Uri=new Uri("pack://application:,,,/WPFDevelopers.Samples;component/ExampleViews/DrawerMenu/EmailPage.xaml" ,UriKind.Absolute ) },
};
Breadcrumbs = breadcrumbItems;
myFrame.Navigate(Breadcrumbs[index].Uri);
BreadcrumbItems = new ObservableCollection<BreadcrumbItem>() { Breadcrumbs[index] };
}
private void BreadCrumbBar_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
myFrame.Navigate(BreadcrumbItem.Uri);
index = BreadcrumbItems.IndexOf(BreadcrumbItem);
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
index += 1;
if (index >= Breadcrumbs.Count) return;
var model = Breadcrumbs[index];
if (BreadcrumbItems.Contains(model))
{
BreadcrumbItem = model;
return;
}
BreadcrumbItems.Add(model);
BreadcrumbItem = model;
}
}
public class BreadcrumbItem
{
public string Text { get; set; }
public Uri Uri { get; set; }
}
}
效果图
来源:https://mp.weixin.qq.com/s/fs4TcsjxA_JLrJ7_TWuzpg


猜你喜欢
- 一、问题Spring2.1.5集成activiti7.1.24时访问要输入用户名和密码。 @Autowired private
- 问题描述:idea输入中文,没输入几个拼音就好像自动回车,有时得到几个字母,然后就不能输入拼音了。遇到这个情况就导致输入中文特别困难,可以采
- 本篇随笔将讲解一下Android当中比较常用的两个布局容器--ScrollView和HorizontalScrollView,从字面意义上来
- 1.1 解决方案名和项目名上右键——重命名如下图:改完后效果如下:1.2 接下来要改名 代码中的名称
- 本篇分享的是springboot多数据源配置,在从springboot v1.5版本升级到v2.0.3时,发现之前写的多数据源的方式不可用了
- eMMC主要是针对手机和平板电脑等产品的内嵌式存储器,由于其在封装中集成了一个控制器,且提供标准接口并管理闪存等优势,越来越受到Androi
- 前言在spring cloud的项目中用到了feign组件,简单配置过后即可完成请求的调用。又因为有向请求添加Header头的需求,查阅了官
- 首先来看一下工具StringUtils的判断方法:一种是org.apache.commons.lang3包下的;另一种是org.spring
- 本文实例讲述了C#操作注册表的方法。分享给大家供大家参考,具体如下:下面我们就来用.NET下托管语言C#注册表操作,主要内容包括:注册表项的
- 代码如下一、创建CheckCode.xaml代码如下<ResourceDictionary xmlns="http
- 如果有人对程序的崩溃原因做下统计的话,那么由于对象为空,但是又访问了对象的某个属性而导致的崩溃,也许会是程序崩溃的第一大原因了。比如我们在使
- 在c和c++中,我们知道没办法起一个变量名叫int,因为这是C/C++保留的关键字,起这么一个变量名没办法区分到底是int类型还是int变量
- Spring是一个非常流行的Java Web开发框架,它提供了强大的依赖注入、面向切面编程、声明式事务管理等功能,为开发者提供了高效、快速地
- 详解java中接口与抽象类的区别1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是
- 数字9 出现的次数编写程序数一下 1到 100 的所有整数中出现多少个数字9源码public static int Getnum
- 这一篇主要是用来介绍关于C#中的XML序列化的问题,这个相信大家一定会经常使用它,特别是在WPF中,有时候我们需要将我们后台的数据保存在数据
- 最近做MVC网站时刚好用到,用以提供一个完整的文件夹并压缩下载,正好做个笔记。拷贝文件夹的所有内容到另一个文件夹内:public stati
- 前言作为Java开发者,我们每天都会创建大量的对象,但是,我们总是使用管理依赖系统(如Spring框架)来创建这些对象。其实还有其他方法可以
- 最近接手了一个需求,要求实现,叮咚买菜。秒杀位置的轮播拆解通过观察发现其实还是挺简单,大致分为1、商品图片的上下轮播2、价格布局渐隐渐现在a
- 什么是“异步调用”?“异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行