WPFのItemsControlでパンくずリストをつくって見ます。
ソースコード
ファイル名:BreadcrumbDemo2.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
ファイル名:App.xaml.cs
using System.Configuration;
using System.Data;
using System.Windows;
namespace BreadcrumbDemo2;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
ファイル名:BreadcrumbItem.cs
// パンくずリストの各項目を表すクラス
public sealed class BreadcrumbItem
{
public string Name { get; set; } = "";
public string FullPath { get; set; } = "";
}
ファイル名:Helpers\RoutedCommandHelper.cs
using System.Windows;
using System.Windows.Input;
public static class RoutedCommandHelper
{
public static RoutedUICommand Create(
Window window,
string? name,
Action<ExecutedRoutedEventArgs> execute,
Func<bool>? canExecute = null,
Key? key = null,
ModifierKeys modifiers = ModifierKeys.None)
{
var cmd = name == null
? new RoutedUICommand()
: new RoutedUICommand(name, name, window.GetType());
ExecutedRoutedEventHandler exec = (_, e) =>
execute(e);
CanExecuteRoutedEventHandler can = (_, e) =>
e.CanExecute = canExecute?.Invoke() ?? true;
window.CommandBindings.Add(
new CommandBinding(cmd, exec, can));
if (key != null)
{
window.InputBindings.Add(
new KeyBinding(cmd, key.Value, modifiers));
}
return cmd;
}
}
ファイル名:Helpers\ViewModelBase.cs
// 汎用的な ViewModel 基底クラス実装。
using System.ComponentModel;
using System.Runtime.CompilerServices;
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
ファイル名:MainViewState.cs
using System.Collections.ObjectModel;
namespace BreadcrumbDemo2;
public class MainViewState : ViewModelBase
{
public ObservableCollection<BreadcrumbItem> Breadcrumbs { get; } = [];
}
ファイル名:MainWindow.xaml.cs
// コードビハインド
using System.Windows;
using System.Windows.Input;
namespace BreadcrumbDemo2;
public partial class MainWindow : Window
{
public MainViewState State { get; } = new();
public RoutedUICommand NavigateCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
NavigateCommand = RoutedCommandHelper.Create(
window: this,
name: "Navigate",
execute: Navigate);
DataContext = this;
this.Loaded += (sender, e) =>
{
this.SetPath("C:\\Users\\karet\\Documets");
};
}
void Navigate(ExecutedRoutedEventArgs e)
{
var x = e.Parameter as BreadcrumbItem;
if (x is null) return;
this.SetPath(x.FullPath);
}
void SetPath(string path)
{
State.Breadcrumbs.Clear();
// Windowsパス想定の簡易分解(最小サンプル)
// 例: "C:\Users\karet" → ["C:", "Users", "karet"]
var parts = path.Split('\\', StringSplitOptions.RemoveEmptyEntries);
// 先頭が "C:" のようなドライブの場合を想定
string current = "";
for (int i = 0; i < parts.Length; i++)
{
var part = parts[i];
if (i == 0 && part.EndsWith(":"))
{
current = part + "\\";
}
else
{
current = current.EndsWith("\\") ? current + part : current + "\\" + part;
}
State.Breadcrumbs.Add(new BreadcrumbItem
{
Name = part,
FullPath = current
});
}
}
}
ファイル名:App.xaml
<Application x:Class="BreadcrumbDemo2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BreadcrumbDemo2"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
ファイル名:MainWindow.xaml
<Window x:Class="BreadcrumbDemo2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BreadcrumbDemo2"
mc:Ignorable="d"
Title="BreadcrumbDemo" Height="450" Width="800">
<Grid Margin="8">
<ItemsControl
ItemsSource="{Binding State.Breadcrumbs}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="24">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
<!-- ItemsControlの項目を水平方向に配置 -->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!-- ItemsControlのItemを水平方向に配置 -->
<!-- 区切り -->
<TextBlock Text=" "
Margin="3,0"
VerticalAlignment="Center" />
<!-- クリック可能なパンくず要素 -->
<Button Content="{Binding Name}"
Padding="2,0"
Margin="0"
Background="Transparent"
BorderThickness="0"
Cursor="Hand"
VerticalAlignment="Center"
Command="{Binding DataContext.NavigateCommand,
RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}" />
<!-- Command ItemsControlをソースに指定 -->
<!-- CommandParameter BreadcrumbItemとバインド -->
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
実行例
スクリーンショット
ディレクトリ名がボタンになっているので、クリックすると変化します。




コメント