TabItemと各TabItemの中身を動的に生成する
やりたいこと
タブと各タブページにボタンを配置する。
タブページの個数と各ページの個数はデータによって変動するのでデータバインドで動的に生成できるようにする。
↓こんな画面を作りたい
XAML
とりあえず全文、各要素の説明は下記。
MainWindow.xaml
<TabControl x:Name="tabControl" Grid.Row="2" Grid.Column="3" Margin="5" ItemsSource="{Binding TabPanels}"> <TabControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Header}" /> </DataTemplate> </TabControl.ItemTemplate> <TabControl.ContentTemplate> <DataTemplate> <ItemsControl ItemsSource="{Binding Buttons}"> <ItemsControl.ItemTemplate> <DataTemplate> <Button Content="{Binding Name}" Margin="4" FontSize="16"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ClickCommand}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel ItemHeight="40" ItemWidth="100" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </DataTemplate> </TabControl.ContentTemplate> </TabControl>
TabControl.ItemTemplate
タブページのヘッダー(タブの名前が表示されるところ)のデザイン設定
名前が表示されればいいのでTextBlock
<TabControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Header}" /> </DataTemplate> </TabControl.ItemTemplate>
TabControl.ContentTemplate
各タブページの内容を記述する
<TabControl.ContentTemplate> <DataTemplate> ~省略~ </DataTemplate> </TabControl.ContentTemplate>
省略の中身、まず画面上に生成するボタンのリストを一段下の階層にItemsControl
のItemsSource
にバインドする。
ItemsControl.ItemTemplate
のDataTemplate
にタブページに表示するボタンを記述する。
ボタンを複数個生成したときに折り返して表示させるためにItemsControl.ItemsPanel
のItemsPanelTemplate
にWrapPanelを指定する。
<ItemsControl ItemsSource="{Binding Buttons}"> <ItemsControl.ItemTemplate> <DataTemplate> <Button Content="{Binding Name}" Margin="4" FontSize="16"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding ClickCommand}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel ItemHeight="40" ItemWidth="100" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl>
ViewModel
ButtonItem.cs
一つのButtonにバインドするクラス
Name
:Buttonに表示する文言を格納
ClickCommand
:Buttonがクリックされたことを受け取る
public class ButtonItem { /// <summary> /// ボタン名称 /// </summary> public string Name { get; set; } #region ClickCommand private Livet.Commands.ViewModelCommand _ClickCommand; public Livet.Commands.ViewModelCommand ClickCommand { get { if (_ClickCommand == null) { _ClickCommand = new Livet.Commands.ViewModelCommand(Click); } return _ClickCommand; } } public void Click() { if (ClickEvent != null) { ClickEvent(this); } } #endregion /// <summary> /// ボタン押下時のイベント /// </summary> public Action<ButtonItem> ClickEvent { get; set; } }
CustomTabItem.cs
一つのTabItemにバインドするクラス
Header
:タブページのヘッダー(タブの名前が表示されるところ)
Buttons
:このページに表示するButtonの情報を保持
public class CustomTabItem { public string Header { get; set; } private ObservableCollection<ButtonItem> Buttons_ = new ObservableCollection<ButtonItem>(); public ObservableCollection<ButtonItem> Buttons { get { return Buttons_; } set { Buttons_ = value; } } }
MainWindowViewModel.cs
TabControlにバインドするオブジェクト
private ObservableCollection<CustomTabItem> TabPanels_ = new ObservableCollection<CustomTabItem>(); public ObservableCollection<CustomTabItem> TabPanels { get { return TabPanels_; } set { TabPanels_ = value; RaisePropertyChanged("TabPanels"); } }
表示内容を設定
public void Initialize() { TabPanels.Add(new CustomTabItem { Header = "TabPanel1", Buttons = { new ButtonItem{Name="Button1", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button2", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button3", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button4", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, } }); TabPanels.Add(new CustomTabItem { Header = "TabPanel2", Buttons = { new ButtonItem{Name="Button1", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button2", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button3", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, new ButtonItem{Name="Button4", ClickEvent = (x)=>{Debug.WriteLine(x.Name);}}, } }); }
参考ページ
非常に参考にさせてもらいました