今回は、WPF で追加削除ボタンつきのタブコントロールをカスタムコントロールライブラリで作成します。
前回はプロジェクト内にカスタムコントロールを作りました。
ライブラリ化することで、他のプロジェクトでも組み込みが容易になります。
やりたいこと
- ライブラリ名: TabAddDel_CustomControlLibrary
- カスタムコントロール名 : TabAddDel_CustomControl
とした場合、

Xamlファイルにカスタムコントロールのタグを追記するだけで、

追加ボタン、削除ボタンを実装したTabControlを生成することです。
- 追加ボタンを押すたび、初期設定のtitle+全タブ数をタイトルとしたタブを生成
- タブを追加されるたびにハンドラを呼び出す
- 先頭のタブは削除ボタンを非表示
- タブを削除すると、タイトルが順番通りになるようにヘッダーを修正
- Windows10
- Microsoft Visual Studio Community2019
- .NET Framework 4.7.2
- WPF アプリ( .NET Framework )
カスタムコントロールライブラリを追加
まずはプロジェクトにカスタムコントロールライブラリを追加します。

ソリューションエクスプローラから、ソリューション→追加→新しいプロジェクト を選択します。

WPF カスタム コントロール ライブラリ( ,NET Framework ) を選択します。次へを押して、ダイアログでプロジェクトの場所を決定します。
次はライブラリを参照できるようにします。
ソリューションエクスプローラーから、参照元のプロジェクト→参照で右クリック → 参照の追加 を選択します。

参照マネージャーでプロジェクト→ソリューションを選択すると追加したカスタムコントロールライブラリが表示されます。チェックすることで参照が有効となります。

カスタムコントロールライブラリの作成
Generic.xaml
ライブラリを作成すると、Generic.xamlが生成されます。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TabAddDel_CustomControlLibrary"> <Style TargetType="{x:Type local:TabAddDel_CustomControl}" BasedOn="{StaticResource {x:Type TabControl}}"> <!-- <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:TabAddDel_CustomControl}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> </ControlTemplate> </Setter.Value> </Setter> --> </Style> </ResourceDictionary>
- StyleタグのBased属性の値にでTabControlを設定します。
- Setter タグ以降は使用しないのでコメントアウトします。
カスタムコントロールのCSファイル
カスタムコントロールのCSファイルは以下となります。
using System; using System.Windows; using System.Windows.Controls; namespace TabAddDel_CustomControlLibrary { public class TabAddDel_CustomControl : TabControl { static TabAddDel_CustomControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TabAddDel_CustomControl), new FrameworkPropertyMetadata(typeof(TabAddDel_CustomControl))); } /// <summary> /// タブ追加したときのイベント /// </summary> public static readonly RoutedEvent AddTabSettingEvent = EventManager.RegisterRoutedEvent( "AddTabSetting", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TabAddDel_CustomControl) ); public event RoutedEventHandler AddTabSetting { add { AddHandler(AddTabSettingEvent, value); } remove { RemoveHandler(AddTabSettingEvent, value); } } /// <summary> /// タブ追加したときのイベントのパラメータ /// </summary> public class AddTabSettingEventArgs : RoutedEventArgs { public TabItem item { get; set; } public AddTabSettingEventArgs(RoutedEvent routedEvent) : base(routedEvent) { } } void RaiseAddTabSettingEvent( TabItem item ) { AddTabSettingEventArgs newEventArgs = new AddTabSettingEventArgs(AddTabSettingEvent); newEventArgs.item = item; RaiseEvent(newEventArgs); } /// <summary> /// タブのタイトル /// </summary> public static readonly DependencyProperty TitleProperty = DependencyProperty.Register( "Title", typeof(String), typeof(TabAddDel_CustomControl), new PropertyMetadata("") ); public static string GetTitle(DependencyObject obj) { return (string)obj.GetValue(TitleProperty); } public static void SetTitle(DependencyObject obj, string value) { obj.SetValue(TitleProperty, value); } /// <summary> /// コントロールの初期化後の処理 /// </summary> public override void EndInit() { base.EndInit(); // 追加ボタン TabItem itemAdd = new TabItem(); itemAdd.Header = "+"; Items.Add(itemAdd); // 最初のタブを追加 AddTabItemCustom(Visibility.Hidden); // イベントを登録 SelectionChanged += SelectedAddDelTab; } /// <summary> /// タブの切り替え時 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void SelectedAddDelTab(object sender, SelectionChangedEventArgs e) { // 追加ボタン(+)を選択する if (SelectedIndex == Items.Count - 1) { // 最初のタブを追加 AddTabItemCustom(Visibility.Visible); // 追加したタブを選択状態にする SelectedIndex = Items.Count - 2; // 追加したタブにフォーカスを設定する ((TabItem)(Items[SelectedIndex])).Focus(); e.Handled = true; } } /// <summary> /// 削除ボタンをクリック /// </summary> /// <param name="item">削除ボタンクリックしたアイテム</param> public void ClickDelButton(TabItem item) { // インデックスを1つ戻す SelectedIndex--; // タブを削除する Items.Remove(item); // タブのタイトルを再設定する for (int i = 1; i < Items.Count - 1; i++) { ((HeaderUserControl)((TabItem)Items[i]).Header).label.Content = GetTitle(this) + (i + 1); } } /// <summary> /// タブの追加 /// </summary> /// <param name="visibility">削除ボタンの表示状態</param> private void AddTabItemCustom(Visibility visibility) { // タブを作成し、追加ボタンの前に追加 TabItem item = new TabItem(); item.Header = new HeaderUserControl(GetTitle(this) + Items.Count, visibility); Items.Insert(Items.Count - 1, item); // イベントハンドラの呼び出し if ( AddTabSettingEvent != null ) { RaiseAddTabSettingEvent(item); } } } }
タブ追加したときのイベント
タブを追加したときに、コントロールを使用する側の関数を呼び出せるようにします。また、関数を呼び出すとき、追加したTabItem もパラメータとして渡します。
タブを追加
タブを追加した後、コントロールを使用する側のイベントハンドラを呼び出します。
それ以外のソースコードの説明は、以下の記事を参考にしてください。
カスタムコントロールを使用する
最後にMainWindowでカスタムコントロールを使用するコードの説明です。
<Window 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:TabAddDelTest" xmlns:TabAddDel_CustomControlLibrary="clr-namespace:TabAddDel_CustomControlLibrary;assembly=TabAddDel_CustomControlLibrary" x:Class="TabAddDelTest.MainWindow" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <TabAddDel_CustomControlLibrary:TabAddDel_CustomControl HorizontalAlignment="Left" Margin="35,35,0,0" VerticalAlignment="Top" Height="285" Width="500" Title="タブ" Visibility="Visible" AddTabSetting="AddTabSetting"> </TabAddDel_CustomControlLibrary:TabAddDel_CustomControl> </Grid> </Window>
TabAddDel_CustomControlLibrary:TabAddDel_CustomControl タグでカスタムコントロールの設定ができます。AddTabSetting プロパティにタブを追加したときのハンドラ関数を指定します。
using System.Windows; using System.Windows.Controls; namespace TabAddDelTest { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void AddTabSetting(object sender, RoutedEventArgs e) { // タブが追加されたとき呼ばれる // ここでは、追加されたタブのコンテンツにユーザーコントロールを設定する TabItem item = ((TabAddDel_CustomControlLibrary.TabAddDel_CustomControl.AddTabSettingEventArgs)e).item; TabItemUserControl control = new TabItemUserControl(); item.Content = control; } } }
AddTabSetting 関数はタブが追加されたとき、ライブラリのカスタムコントロールから呼ばれます。関数内で、追加したTabItemのコンテンツにユーザーコントロールを設定します。
まとめ
WPF で追加削除ボタンつきのタブコントロールをカスタムコントロールライブラリで作成しました。
コメントを残す
コメントを投稿するにはログインしてください。