I have bumped into a problem to which I am seeking the solution.
I have a tabControl with styles added to it.
I want to display only images on each TabItem.Header and when that tab is selected then hide the image from header and display text (the other, inactive headers will be showing images).
Can anybody provide any help?
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Borderer" Background="#FF777777" Height="70" Width="90">
<ContentPresenter x:Name="ContentTabItem" ContentSource="Header" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="#FF000000" />
<Setter TargetName="Borderer" Property="Background" Value="WhiteSmoke" />
<Setter Property="Header" >
<Setter.Value>
<Grid>
<ContentPresenter ContentSource="Tag" />
</Grid>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl Height="189" HorizontalAlignment="Left" Margin="94,123,0,0" Name="tabControl1" VerticalAlignment="Top" Width="500">
<TabItem Name="tabItem1" IsSelected="True" >
<TabItem.Tag>
<TextBlock Text="blab lab la" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img1.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="aaa" />
</Grid>
</TabItem.Content>
</TabItem>
<TabItem >
<TabItem.Tag>
<TextBlock Text="la lab blab" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img2.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="bbb" />
</Grid>
</TabItem.Content>
</TabItem>
</TabControl>
</Grid>
You can actually do this without replacing the whole ControlTemplate on the TabItem. You can just alter the TabItem's HeaderTemplate when the TabItem is selected, making your Style a lot shorter:
<DataTemplate x:Key="SelectedHeaderTemplate" >
<ContentControl Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem},
Path=Tag}" />
</DataTemplate>
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate" Value="{StaticResource SelectedHeaderTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
Related
I have for example a combobox and if it is not chosen then I am displaying an error message under it.
When the message is displayed it is displayed on top of the control that is under the combobox.
Is there a way to move the control(s) under the combobox down when the error message is shown?
<UserControl.Resources>
<Style x:Key="ErrorStackPanel" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Margin" Value="0 20 0 5"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ErrorComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="MinWidth" Value="180" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True">
<!--Placeholder for the TextBox itself-->
<AdornedElementPlaceholder x:Name="textBox" />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent}"
Foreground="Maroon"
FontWeight="Bold"
Margin="5 2 0 0"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="2" Margin="10 5">
<Label Content="Switch" />
<ComboBox Style="{StaticResource ErrorComboBox}" ItemsSource="{Binding Switches}" SelectedItem="{Binding SelectedSwitch}"
DisplayMemberPath="Name" HorizontalAlignment="Left">
</ComboBox>
</StackPanel>
<StackPanel Grid.Row="3" Margin="10 10" Style="{StaticResource ErrorStackPanel}">
<RadioButton GroupName="pres"
IsChecked="{Binding TriggerOnPress}"
Content="On" Margin="0 5" />
<RadioButton GroupName="pres"
IsChecked="{Binding TriggerOnPress, Converter={valueconverters:BoolInverterConverter}}"
Content="Off" Margin="0 5"/>
</StackPanel>
StackPanel doesn't have error state. Apply trigger to ComboBox and change bottom margin:
<Style x:Key="ErrorComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="MinWidth" Value="180" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
...
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Margin" Value="0 0 0 20"/>
</Trigger>
</Style.Triggers>
</Style>
I want to show Image inside of the Title of header in TabControl
This question(WPF TabItem - Image Binding) seems is right, but I have using Triggers and it doesn't help on my code.
Here is what I have Providing:
<TabControl Name="MainTabControl" Margin="0,28,0,0" TabStripPlacement="Top" >
<TabControl.Resources>
<Image x:Key="imgProfile" Source="/Icons/red icons/profile.png" />
<Image x:Key="imgComment" Source="Icons/red icons/notification.png" />
<Style TargetType="TabItem" >
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding}"
MouseDown="UIElement_OnMouseDown"
FontSize="18"
/>
<Image Height="25" Margin="4,0,4,0"
Source="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag.Source}" />
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Gainsboro" CornerRadius="0" Margin="2,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="5,2"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent" />
<Setter TargetName="Border" Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource TabItemNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Name="tiProfile" Header="a" Tag="{StaticResource imgProfile}"></TabItem>
<TabItem Name="tiComment" Header="b" Tag="{StaticResource imgComment}"></TabItem>
</TabControl>
the binding from TabItem.HeaderTemplate to the TabItem.Tag must be via FindAncestor of TabItem type.
instead create Images in Resources, create BitmapImage, and bind it the Image.Source.
so, Resources:
<BitmapImage x:Key="imgProfile" Source="/Icons/red icons/profile.png" />
<BitmapImage x:Key="imgComment" Source="Icons/red icons/notification.png" />
Header DataTemplate:
<Image Height="25" Margin="4,0,4,0"
Source="{Binding Tag, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}" />
I am trying to set up a sort of menu using ListBox and buttons as ListBoxItems to trigger a command when selection changes, but the result is that some times the selected ListBoxItem is changed but the command is not triggered, other times the opposite. The XAML is the following:
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TripViewModel}">
<views:TripView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:AddTripViewModel}">
<views:AddTripView />
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Height"
Value="50" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Grid Background="Transparent">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding"
Value="3" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.Content>
<DockPanel Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
LastChildFill="True">
<!-- Left Panel -->
<Border BorderBrush="Black"
BorderThickness="0,0,1,0">
<StackPanel DockPanel.Dock="Left"
Margin="0"
Background="#555D6F">
<!-- First Row: Stacco Image -->
<Image Height="183"
Width="275"
Margin="3"
Source="/Media/stacco.png" />
<!-- Second Row: Buttons -->
<ScrollViewer CanContentScroll="True"
VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Auto"
Margin="0,10,0,0">
<ListBox Name="MenuButtons"
ItemsSource="{Binding PageViewModels}"
Background="#555D6F"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</StackPanel>
</Border>
<!-- Control Area: Different View made by controls -->
<ContentControl DockPanel.Dock="Right"
Content="{Binding CurrentPageViewModel}" />
</DockPanel>
</Window.Content>
Am I doing right trying to insert a button in the ItemContainerTemplate? Would it be better to use the code behind to trigger the selection changed?
How could I make the tabitem(header) border in alignment with the content part. Below I put the item header in grid. I've attached a picture. There's some tiny space at left. The same thing to the top part. I want it to be filled.
<Grid>
<TabControl Margin="10" BorderThickness="2" Background="LightGray" Padding="0">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="30,3"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Header="General">
<Label Content="Content goes here..." />
</TabItem>
<TabItem Header="Security" />
<TabItem Header="Details" />
</TabControl>
</Grid>
Default template of TabItem have margin of -1 but in your case you have border thickness of 2 set. So margin of -2 should work for you.
Set margin on Grid:
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel" Margin="-2,-2,-2,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="30,3"/>
</Grid>
.....
Set the margin for the TabItem instead of Tab
<TabItem Header="General", Margin="0,0,0,0"/>
Set the margin for the TabItem to 0, this will override the default margin and work as per your requirements
I have a TabControl containing TabItems. I overwrote their ItemTemplate to contain:
A TextBlock showing the caption of the TabItem
A Button (X) which closes the tab
Now I would like to make the "X"-Button only visible, when the TabItem is either selected or the mouse is over it.
This is my XAML code so far...
<TabControl x:Name="tabControl"
ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding TabCaption}"
Grid.Column="0"
Foreground="White"
HorizontalAlignment="Left"
Margin="3"
Name="label_TabTitle"
VerticalAlignment="Center" />
<Button Content="X"
Grid.Column="1"
Foreground="White"
HorizontalAlignment="Right"
Margin="3"
Name="button_close"
VerticalAlignment="Center"
Width="20"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Visibility="Hidden"
Click="button_close_Click_1">
</Button>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="button_close" Property="Visibility" Value="Visible"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Background" Value="#1C1C1C" />
<Setter Property="Content" Value="{Binding TabContentView}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Grid"
Background="{StaticResource GrayBrush}">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource BlueBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource LightBlueBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
With the Trigger inside the DataTemplate it kind of works.. but: you have to hover the mouse directly over the Label in order to show the button. So basically, it is impossible to click the button, because it disappears again.
I would appreciate any help with these WPF Templates!
Thanks, Christian
It looks as though your TabItem does not have the background set so it is not catching the MouseOverEvent. Since the TextBlock has the foreground set and has text, it captures the MouseOverEvent. Try setting the Background child grid of the DataTemplate to Transparent and you should see that the MouseOverEvent will be caught and show the close button.
<TabControl x:Name="tabControl" ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center" Background="Transparent">
...
</Grid>
...
</DataTemplate>
</TabControl.ItemTemplate>
...
</TabControl>
If you set opacity instead of visibility it works. Removed all references to Visibility, changed to Opacity:
You may want to check my code edit. Not 100% sure it's a duplicate of what you had, but the idea works. Why? Not sure. :) I'm guessing the Hidden-Button was swallowing the MouseEnter events, but refusing to pass them on because it was hidden.
<TabControl x:Name="tabControl"
ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding TabCaption}"
Grid.Column="0"
Foreground="White"
HorizontalAlignment="Left"
Margin="3"
Name="label_TabTitle"
VerticalAlignment="Center" />
<Button Content="X"
Grid.Column="1"
Foreground="White"
HorizontalAlignment="Right"
Margin="3"
Name="button_close"
VerticalAlignment="Center"
Width="20"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Opacity="0"
Click="button_close_Click_1">
</Button>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="button_close" Property="Opacity" Value="1"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Background" Value="#1C1C1C" />
<Setter Property="Content" Value="{Binding TabContentView}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Grid"
Background="{StaticResource GrayBrush}">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource BlueBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource LightBlueBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>