I have a WPF xaml TabControl defined as below, how to set Visibility to Collapsed for the tab item based on binding? Current code:
<TabControl>
<DataTemplate DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
<DataTemplate DataType="{x:Type bar:BarViewModel}">
<bar:BarView/>
</DataTemplate>
<TabControl/>
What I want to implement to only hide foo TabItem based on condition, but seems it cannot specify the target name?? E.g. hide the template which name is Foo. Thanks for your help, have a nice day.
<TabControl ItemsSource="{Binding ParentModel}">
<DataTemplate x:Name="Foo" DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
<DataTemplate x:Name="Bar" DataType="{x:Type bar:BarViewModel}">
<bar:BarView/>
</DataTemplate>
<TabControl.ItemContinerStyle>
<Style TargetType="TabItem" 'e.g. TargetName="Foo"<==========='>
<Style.Triggers>
...Some trigger condition ignored here
<Setter Property="Visibility" Value="Collapsed" />
</Style.Triggers>
</Style>
<TabControl.ItemContinerStyle/>
<TabControl/>
CodePudding user response:
Hiding the TabItem
element is visually equivalent to removing the element.
Since you use data templating, the usual procedure would be to filter the source collection based on your condition to remove the data model. Removing the data model will result in the corresponding container (defined by the DataTemplate
) not being rendered i.e. it will be hidden.
In WPF you always focus on the data models and not on their containers. It makes thinks a lot easier.
In the view model that defines the ParentModel
property, you can define the filter by accessing the ICollectionView
of the source collection:
private void ApplyFilter()
{
ICollectionView parentModelView = CollectionViewSource.GetDefaultView(this.ParentModel);
// Remove all items from the view that satisfy the condition
parentModelView.Filter = Predicate;
}
private bool Predicate(object collectionItem)
{
// TODO::Implement condition: return 'true' to hide the item from the view
}
If you want to filter the view directly (not recommended) you can access the ItemsControl.Items
property to obtain the current ICollectionView
:
private void OnMainWIndowLoaded(object sender, EventArgs e)
{
this.TabControl.Items.Filter = Predicate;
}
private bool Predicate(object collectionItem)
{
// TODO::Implement condition: return 'true' to hide the item from the view
}
CodePudding user response:
Can't you simply control it on the element?
<TabControl>
<TabItem Header="Tabitem 1" Visibility="{Binding TabItem1Visibility, Converter={StaticResource BoolToVisibilityConverter}}"/>
<TabItem Header="Tabitem 2" />
<TabItem Header="Tabitem 3" />
</TabControl>
where TabItem1Visibility is a property in your VM:
private bool _tabItem1Visibility;
public bool TabItem1Visibility
{
get { return _tabItem1Visibility; }
set
{
_tabItem1Visibility = value;
OnPropertyChanged();
}
}
Notes:
BoolToVisibilityConverter
'sConvert
method must returnCollapse
in case the value isfalse
, notHidden
.- If you set
TabItem1Visibility
tofalse
while the tab is selected, the content will still shown up, so you have to addSelectedItem="{Binding SelectedTab, Mode=TwoWay}"
toTabControl
and update it properly.