トップ回答者
WPF TabControlアクティブ状態のレイアウト設定方法について

質問
-
現在WPFでアプリケーションを開発しております。
TabControlについて、アクティブ状態のタブと非アクティブ状態のタブで上下に若干の隙間があるため、状態に関わらず共通したレイアウトに変更したいと思います。
お手数ではありますが、アクティブ状態を検知したレイアウトの設定方法、もしくはTabControlのContainerStyleを指定する方法など、何か参考になる毒キュメンとがありましたら教えていただけると幸いです。(コードでも構いません。)現在想定しているデザインは、アクティブ状態のタブのみ背景色を変更する、隙間やボーダーは表示しないフラットデザインに寄せたコントロールにしたいと考えております。
よろしくお願いいたします。
回答
-
デザイナへTabControlを配置して、適当にItemSourceを設定します。たとえば以下のような
<TabControl ItemsSource="{Binding}" DataContext="ABCD" />
デザイナのデザインでタブコントロールを右クリックして「テンプレートの編集->コピーして編集」を選択するとTabConrolのスタイルがリソースにつくられます。
その中のTemplateプロパティ対象のセッターで、TabPanelを探してMargin等を変更します。(Tabが上以外の場合はTriggersでHeaderPanelを対象にしたMarginも変更します。
一端このTabControlに適用されたスタイルを消すか、リソースのスタイルをコメントアウトするか、どこかにコピーしておいて消しておきます。再度デザイナでタブコントロールを右クリックして「追加テンプレートの編集->生成されたアイテムコンテナーの編集->コピーして編集」を選択します。(表示されない場合はいったんデザイナを閉じます。)
その中のTemplateプロパティ対象のセッターで、IsSelected=trueになっているMultiTriggerを探して、Marginを変更するセッターを変更します。必要ならBackgroundを変更するセッターを追加します。
先の無効にしておいたTabControlのスタイルを再度適用できるように戻します。後は好きなようにボーダーなどをいじってみてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2017年3月12日 15:53
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年3月13日 4:31
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年3月22日 0:48
-
できますがSelectedItemやSelectedIndexを使った方が楽だと思います
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel> <UniformGrid Columns="2" Rows="1"> <DockPanel> <StackPanel DockPanel.Dock="Bottom"> <CheckBox x:Name="chA" Content="A"/> <CheckBox x:Name="chB" Content="B"/> </StackPanel> <TabControl> <TabItem Header="A" x:Name="a"> <TabItem.Style> <Style TargetType="TabItem"> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsChecked,ElementName=chA}" Value="true"> <Setter Property="IsSelected" Value="true" /> </DataTrigger> </Style.Triggers> </Style> </TabItem.Style> </TabItem> <TabItem Header="B" x:Name="b"> <TabItem.Style> <Style TargetType="TabItem"> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=IsChecked,ElementName=chA}" Value="false" /> <Condition Binding="{Binding Path=IsChecked,ElementName=chB}" Value="true" /> </MultiDataTrigger.Conditions> <Setter Property="IsSelected" Value="true" /> </MultiDataTrigger> </Style.Triggers> </Style> </TabItem.Style> </TabItem> </TabControl> </DockPanel> <TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding Path=CurrentItem}" > <TabControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Text}"/> </DataTemplate> </TabControl.ItemTemplate> </TabControl> </UniformGrid> </DockPanel> </Window>
Class MainWindow Sub New() InitializeComponent() Me.DataContext = New Model() End Sub End Class Class Model Implements System.ComponentModel.INotifyPropertyChanged Public Sub New() _Items = New System.Collections.ObjectModel.ObservableCollection(Of Item)() _Items.Add(New Item() With {.Text = "AAA"}) _Items.Add(New Item() With {.Text = "BBB"}) _Items.Add(New Item() With {.Text = "CCC"}) Me.CurrentItem = Me.Items(1) End Sub Public ReadOnly Property Items As System.Collections.ObjectModel.ObservableCollection(Of Item) Get Return _Items End Get End Property Private _Items As System.Collections.ObjectModel.ObservableCollection(Of Item) Public Property CurrentItem As Item Get Return _CurrentItem End Get Set(value As Item) _CurrentItem = value OnPropertyChanged("CurrentItem") End Set End Property Private _CurrentItem As Item Public Event PropertyChanged(sender As Object, e As ComponentModel.PropertyChangedEventArgs) Implements ComponentModel.INotifyPropertyChanged.PropertyChanged Protected Sub OnPropertyChanged(ByVal name As String) RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name)) End Sub End Class Class Item Public Property Text As String End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年3月16日 0:16
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年3月22日 0:48
すべての返信
-
デザイナへTabControlを配置して、適当にItemSourceを設定します。たとえば以下のような
<TabControl ItemsSource="{Binding}" DataContext="ABCD" />
デザイナのデザインでタブコントロールを右クリックして「テンプレートの編集->コピーして編集」を選択するとTabConrolのスタイルがリソースにつくられます。
その中のTemplateプロパティ対象のセッターで、TabPanelを探してMargin等を変更します。(Tabが上以外の場合はTriggersでHeaderPanelを対象にしたMarginも変更します。
一端このTabControlに適用されたスタイルを消すか、リソースのスタイルをコメントアウトするか、どこかにコピーしておいて消しておきます。再度デザイナでタブコントロールを右クリックして「追加テンプレートの編集->生成されたアイテムコンテナーの編集->コピーして編集」を選択します。(表示されない場合はいったんデザイナを閉じます。)
その中のTemplateプロパティ対象のセッターで、IsSelected=trueになっているMultiTriggerを探して、Marginを変更するセッターを変更します。必要ならBackgroundを変更するセッターを追加します。
先の無効にしておいたTabControlのスタイルを再度適用できるように戻します。後は好きなようにボーダーなどをいじってみてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2017年3月12日 15:53
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年3月13日 4:31
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年3月22日 0:48
-
できますがSelectedItemやSelectedIndexを使った方が楽だと思います
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel> <UniformGrid Columns="2" Rows="1"> <DockPanel> <StackPanel DockPanel.Dock="Bottom"> <CheckBox x:Name="chA" Content="A"/> <CheckBox x:Name="chB" Content="B"/> </StackPanel> <TabControl> <TabItem Header="A" x:Name="a"> <TabItem.Style> <Style TargetType="TabItem"> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsChecked,ElementName=chA}" Value="true"> <Setter Property="IsSelected" Value="true" /> </DataTrigger> </Style.Triggers> </Style> </TabItem.Style> </TabItem> <TabItem Header="B" x:Name="b"> <TabItem.Style> <Style TargetType="TabItem"> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=IsChecked,ElementName=chA}" Value="false" /> <Condition Binding="{Binding Path=IsChecked,ElementName=chB}" Value="true" /> </MultiDataTrigger.Conditions> <Setter Property="IsSelected" Value="true" /> </MultiDataTrigger> </Style.Triggers> </Style> </TabItem.Style> </TabItem> </TabControl> </DockPanel> <TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding Path=CurrentItem}" > <TabControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Text}"/> </DataTemplate> </TabControl.ItemTemplate> </TabControl> </UniformGrid> </DockPanel> </Window>
Class MainWindow Sub New() InitializeComponent() Me.DataContext = New Model() End Sub End Class Class Model Implements System.ComponentModel.INotifyPropertyChanged Public Sub New() _Items = New System.Collections.ObjectModel.ObservableCollection(Of Item)() _Items.Add(New Item() With {.Text = "AAA"}) _Items.Add(New Item() With {.Text = "BBB"}) _Items.Add(New Item() With {.Text = "CCC"}) Me.CurrentItem = Me.Items(1) End Sub Public ReadOnly Property Items As System.Collections.ObjectModel.ObservableCollection(Of Item) Get Return _Items End Get End Property Private _Items As System.Collections.ObjectModel.ObservableCollection(Of Item) Public Property CurrentItem As Item Get Return _CurrentItem End Get Set(value As Item) _CurrentItem = value OnPropertyChanged("CurrentItem") End Set End Property Private _CurrentItem As Item Public Event PropertyChanged(sender As Object, e As ComponentModel.PropertyChangedEventArgs) Implements ComponentModel.INotifyPropertyChanged.PropertyChanged Protected Sub OnPropertyChanged(ByVal name As String) RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name)) End Sub End Class Class Item Public Property Text As String End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年3月16日 0:16
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年3月22日 0:48