TabItem - how to change template and leave default style? - wpf

I have the following code:
<Window x:Class="kkk.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">
<Window.Resources>
<Style x:Key="tabitemstyle" TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter x:Name="ContentSite" ContentSource="Header"></ContentPresenter>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl>
<TabItem Header="tab1" Style="{StaticResource tabitemstyle}"></TabItem>
<TabItem Header="tab1" Style="{StaticResource tabitemstyle}"></TabItem>
</TabControl>
</Grid>
</Window>
I want to preserve the default style of TabItem - I mean the padding/margins/BorderBrush/BorderThickness and so on... That is why I wrote BasedOn="...".
But it doesn't work - I thought it will render same as TabItem without any custom style but it doesn't - it just renders some text (by the ContentPresenter). The style doesn't get default properties values... How I can do it?
And I need the ControlTemplate inside my style...

You are overwriting the TabItem.Template, which is what tells WPF how to draw the object
If you want to create a template that is based on the default TabItem.Template, you can get the default template from MSDN and alter it to whatever you want.

Related

Why can't I see the control of my WPF custom control?

I have followed the solution of this question: how to have many wpf custom controls in the same library?
The problem now is that I can see the controls of my custom control when I add the custom control in my main view.
However, if I have the style in the generic.xaml file instead of the MyControl.xaml file, and only I have ona user control, it works.
The code of my MyControl.xaml is this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<Style TargetType="{x:Type local:CalendarioMes2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioMes2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<TextBox Text="Prueba" BorderBrush="Black"/>
<Label Content="Prueba" BorderBrush="black"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And the generic.xaml has this code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CustomControls.Calendario2;component/ResourceDictionaries/CalendarioMes2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Why can't I see the textBox and the label?
Thanks.
EDIT: I have use the absolute path to the file:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="F:\Alvaro\ejemplos\Calendario\CustomControls\Themes\CalendarioMes2.xaml"/>
</ResourceDictionary.MergedDictionaries>
But know I have an error in the main window that say that I can create a type from the text. The error is in the CalendarioMes2.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls.Calendario2">
<Style TargetType="{x:Type local:CalendarioMes2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioMes2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<TextBox Text="Prueba" BorderBrush="Black"/>
<Label Content="Prueba" BorderBrush="black"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
In the line 7:
<Style TargetType="{x:Type local:CalendarioMes2}">
But compare my code with the code of the solution in the other thread, I see that I have the same line.
This is CalendarioMes2.cs
namespace CustomControls.Calendario2
{
public class CalendarioMes2 : Control
{
static CalendarioMes2()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarioMes2), new FrameworkPropertyMetadata(typeof(CalendarioMes2)));
}
}
}
EDIT: the source code is here: https://1drv.ms/u/s!AiTepLSbavZ0gRDvBPJgrxEIWS1U

Silverlight create control template for TabControl

I use Silverlight 5 and want to use control template for TabControl. how can do it.
In WPF you can use below code for control template of TabControl
<Style TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<TabPanel Grid.Column="1" Name="HeaderPanel" IsItemsHost="True"/>
<ContentPresenter Grid.Column="0" ContentSource="SelectedContent"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks in advance.
By far the easiest way to customise the TabControl template is with Expression Blend.
However, the ControlTemplate for a Silverlight TabControl should look mostly the same as your example. There are a couple of notable differences though.
TargetType syntax is different
TargetType="TabControl"
There is also no ContentSource property on the ContentPresenter

WPF: Problem applying style to custom TabItem Header through ControlTemplate and ContentPresenter.Resources

I am trying to write my own control template for a TabItem Header, and have got the basic layout to work but now I wish to apply styling to the content of the Header, for example to manipulate the size and font of a textblock.
In order to test this, I have put an ellipse in the tabitem header and am attempting to fill that ellipse with the Gold brush through styling. However, it is not working. The ellipse is present, and the control template is being applied, but the fill of the ellipse is not Gold. The style within the ContentPresenter.Resources is being ignored (and Resharper has even greyed it out to prove that). Any ideas what I'm doing wrong? Thanks.
Here is the code:
<TabItem>
<TabItem.Template>
<ControlTemplate x:Name="theTabItemControlTemplate" TargetType="{x:Type TabItem}">
<Border BorderBrush="DarkBlue" BorderThickness="10">
<Grid>
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True">
<ContentPresenter.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Ellipse.Fill" Value="Gold"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</TabItem.Template>
<TabItem.Header>
<Ellipse Stroke="Black" StrokeThickness="2" Width="100" Height="30" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</TabItem.Header>
</TabItem>
Move your style one level upper.ie,move it to ControlTemplate.Resources and it will work fine.I am quite not sure why the code in the question does not work.It may be because the controls in the contentpresenter is already built by the time the style is encountered.
<ControlTemplate x:Name="theTabItemControlTemplate" TargetType="{x:Type TabItem}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Fill" Value="Red"/>
</Style>
</ControlTemplate.Resources>
<Border BorderBrush="DarkBlue" BorderThickness="10">
<Grid>
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>

WPF GroupBox ControlTemplate : How to apply a Style only to elements in the Header?

I'm trying to make a ControlTemplate for a GroupBox such that if a TextBlock is declared in the Header its Background should be set to yellow.
The problem is that, although I define a style for TextBlocks in the ContentPresenter for the Header, it's not applied except on those TextBlocks which are autogenerated by WPF.
Here is the code :
<Window
x:Class="TestHeaderTemplate.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
SizeToContent="WidthAndHeight">
<Window.Resources>
<Style
TargetType="{x:Type GroupBox}">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type GroupBox}">
<Border
Margin="{TemplateBinding Margin}"
BorderBrush="Black"
BorderThickness="1">
<StackPanel>
<Border
Margin="0,0,0,5"
BorderThickness="5"
BorderBrush="LightBlue"
>
<ContentPresenter
ContentSource="Header">
<ContentPresenter.Resources>
<Style
TargetType="{x:Type TextBlock}">
<Setter
Property="Background"
Value="Yellow" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
<ContentPresenter
ContentSource="Content" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<TextBox
Text="All TextBoxes in a GroupBox's Header should be yellow, whether declared or autogenerated." />
<GroupBox
x:Name="firstGroupBox"
Margin="5"
Header="I am a TextBlock autogenerated by WPF. Since I'm in the Header, I should be yellow.">
<TextBlock
Text="I'm a TextBlock declared in the content of the GroupBox. I should NOT be yellow." />
</GroupBox>
<GroupBox
x:Name="secondGroupbox"
Margin="5"
>
<HeaderedContentControl.Header>
<TextBlock
x:Name="notStyledTextBlock"
Text="I'm a TextBlock declared in the header. I should be yellow since I'm in the header."
VerticalAlignment="Center" />
</HeaderedContentControl.Header>
<TextBlock
Text="I'm declared in the content so I should not be yellow." />
</GroupBox>
</StackPanel>
</Window>
As you can see if you try, the background of the TextBlock named notStyledTextBlock in the second GroupBox is not yellow, which means the style defined in the resources of the ContentPresenter in the ControlTemplate is not applied.
Surprisingly, the one that was autogenerated by WPF as a container for the header text of the first GroupBox has its background yellow.
What can I do to make it so my style is applied to the notStyledTextBlock TextBlock?
I had also problems with GroupBoxes and ContentPresenter. I have posted a question and because no answer was given I investigated myself a little. Look at this answer, maybe its the same issue (Additional info: I have not posted my real problem-code but a simplified example that could be used to reproduce).

Does anyone have a simple example of a UserControl with a single ContentPresenter?

So far, I have this:
<UserControl
x:Class="MyConcept.ExpanderPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Border
Style="{StaticResource Border_PanelStyle}"
CornerRadius="3" />
<ContentPresenter />
</Grid>
</UserControl>
Sample usage of this UserControl:
<nc:ExpanderPanel
Grid.Row="0">
<Expander
IsExpanded="True"
Header="NMT Users">
<StackPanel>
...
</StackPanel>
</Expander>
</nc:ExpanderPanel>
Discussion
If I run this, I see nothing. No content is presented, not even the border that is built into the UserControl.
I thought maybe I needed to make the ContentPresenter a dependency property, but I couldn't figure out how I would link the property to the ContentPresenter in the UserControl's XAML.
Can someone provide a simple example that shows how to build a UserControl (or some kind of custom control) with a single ContentPresenter?
ContentPresenters are main used in ControlTemplates and bound with a TemplateBinding to the ContentControl.Content.
from this site... a control template for a button that uses a ContentPresenter
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}" />
<ContentPresenter
Content="{TemplateBinding Property=ContentControl.Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources