I have a WPF application (.NET 3.0, VS2008) that displays data in a tab control. Custom colors are required on virtually all controls in this application : basically white foreground and green background.
My problem is that when an XP theme (say Luna) is active, it is automatically applied to render controls so that my white text is written on ... a white background. For instance on the active tab item header :
I have tried :
to remove the embedded manifest file from the generated application (in the project properties) : useless.
to force the use of the Windows Classic theme in the application resources :
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Classic;V3.0.0.0;31bf3856ad364e35;component/themes/classic.xaml" />
</ResourceDictionary.MergedDictionaries>
This last attempt worked great for all controls, except the tab control which still displays as above.
Any idea ?
Update : I am suspecting this behaviour is due to the custom style I have to apply to the tab control :
<Window.Resources>
<Style x:Key="Custom">
<Setter Property="Control.Background" Value="#FF47C7C8" />
<Setter Property="Control.Foreground" Value="White" />
</Style>
<Style TargetType="TabControl" BasedOn="{StaticResource Custom}" />
</Window.Resources>
So how can I get the classic theme with custom colors ?
Your best bet, to ensure a consistent behavior and appearance across operating systems, would be to re-template the TabItem control and then use a Trigger to modify a part of your new template when a TabItem is selected. Try something like the following:
<Grid>
<Grid.Resources>
<Style x:Key="Custom">
<Setter Property="Control.Background" Value="#FF47C7C8"/>
<Setter Property="Control.BorderBrush" Value="#FF47C7C8"/>
<Setter Property="Control.Foreground" Value="White"/>
</Style>
<Style BasedOn="{StaticResource Custom}" TargetType="TabControl"/>
<Style TargetType="TabItem">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Background="#FF47C7C8"
BorderBrush="#FFFFFF"
BorderThickness="1,1,1,1"
CornerRadius="2,2,0,0">
<ContentPresenter
x:Name="ContentSite"
HorizontalAlignment="Center"
Margin="12,2,12,2"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100"/>
<Setter TargetName="Border" Property="Background" Value="#FF47C7C8"/>
<Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<TabControl>
<TabItem Header="Item 1"/>
<TabItem Header="Item 2"/>
<TabItem Header="Item 3"/>
<TabItem Header="Item 4"/>
</TabControl>
Bon chance!
Why don't you use the WPF Themes from the WPF Futures project!
WPF Themes
alt text http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=wpf&DownloadId=62497
Related
My first steps in WPF and C# and i don't get it to work... :(
I have an application with two grids inside one window. I have to change the style of the first grid, so i started reading and reached using ControlTemplate.
My Grid now looks as i wanted it. But i only want that the first grid looks this way. the second one on the same page should have another style.
Is it possible to bind the controltemplate only on one grid. Maybe by name or soemthing identifying?
My ControlTemplate Code for now i have written in window.resources looks:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Margin="0,0,0,0"
Background="Black"
BorderBrush="Black"
BorderThickness="0,2,0,0"
CornerRadius="0,0,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="0,0,0,20"
RecognizesAccessKey="True"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#FF454E54" />
<Setter TargetName="Border" Property="Background" Value="#FF0A3651" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="White" />
<Setter TargetName="Border" Property="Background" Value="#FF454E54" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You could give the Style or ControlTemplate an x:Key ( <Style x:Key="key" TargetType="{x:Type TabItem}"> ) and apply it to the element you want by setting the element's Style or Template property like this:
<TabItem Style="{StaticResource key}">
A Style without an x:Key is implicit and will be applied to all elements whose type matches the specified TargetType of the Style.
Instead of writing your template under Window.Resources do it under your Grid.Resources
Try this. All this is doing is setting the style of the TabItem directly.
<TabItem> <!-- This is your TabItem control -->
<TabItem.Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<!-- ControlTemplate here -->
</Controltemplate
</Setter.Value>
</Setter>
</Style>
</TabItem.Style>
</TabItem>
I've created in my Window.Resource a Style that hold the background of the selected TabItem. What I want achieve is set a custom height for the TabItem header, this is my Style:
<Window.Resources>
<ResourceDictionary>
<Style x:Key="CustomTabItem" TargetType="{x:Type TabItem}" BasedOn="{StaticResource MetroTabItem}">
<Setter Property="Width" Value="Auto"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Height" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" Background="Transparent">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Left"
ContentSource="Header"
Margin="10,3">
</ContentPresenter>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" SourceName="Border">
<Setter TargetName="Border" Property="Background" Value="Gainsboro" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="#FFC5C5C5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
usually I add the style to my TabControl like so:
<TabItem Tag="Tab1" Style="{StaticResource CustomTabItem}">
I just want set the header height for all the TabControls that have the CustomTabItem style, any suggestion?
You are making a confusion between TabControl and TabItem.
A TabControl has many TabItems.
Each TabItem is actually a Tab.
So the solutions are :
1 Set Style to all TabItems of all TabControls
A very simple way to apply the style is to remove the x:Key attribute of the TabItem style, and the style will apply to all TabItems
<!-- No x:Key="CustomTabItem" below -->
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource MetroTabItem}">
2 Set Style for all tabs of a TabControl
<TabControl ItemContainerStyle="{DynamicResource TabItemStyle1}" >
<TabItem Header="Hello">Hello content</TabItem>
<TabItem Header="Goodye">Goodbye content</TabItem>
</TabControl>
3 Set Style per TabItem
<TabControl>
<TabItem Style="{StaticResource CustomTabItem}" Header="Hello">Hello content</TabItem>
<TabItem Header="Goodye">Goodbye content</TabItem>
</TabControl>
Regards
Iam trying to create a custom Window which will contain some custom Properties. When I run the Application all things go fine but the problem that the xaml designer never recognize these properties
Also the Window's OnApplyTemplate method not working under designer
<Style TargetType="{x:Type windows:MDWindow}">
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type windows:MDWindow}">
<Grid >
<!--This Never Changed At Design Time-->
<TextBlock Text="{TemplateBinding Title}"></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
this is a two part question that probbably have a similar answer.
I want to create in a resource dictionary a style for a label that contains first an image and then the text. The text, as a TextBlock has it's own style (had no problems there). Here is what I have
Label Style:
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<TextBlock Style="{StaticResource TextBlockStyle}">
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TextBlockStyle:
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="25 0 0 2.5"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextDecorations" Value="Underline"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
Now my problem is when I add a new label to my Control (ex: Window) and specify the text (ex: Create), no text is shown.Something like:
<Label Style="{StaticResource LabelStyle}">Create</Label>
The text Create does not show, however if I put in my LabelStyle->TextBlock->text it shows, but it's no good since I want to change it for different labels. Is there a way to bind my Label text to my (Inside Style) TextBlock.Text???
My other question is the same, but for images, and Image.Source.
Thanks :-)
EDIT:
This is what I have now with H.B. answer implemented
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Grid>
<StackPanel Orientation="Horizontal">
<Image Source="/Resources/Create.png" />
<TextBlock Style="{StaticResource TextBlockStyle}" Text="{TemplateBinding Content}"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note that this is in the Resource Dictionary. For the TextBlock it works great. But for the image it's a different story. I want the same as the 'Text="{TemplateBinding Content}' but for the Image.Source and set it's path in my control when I add the label. Probabbly since it's multiple content I'll have to write more code than I'd like, but I'll settle for the easiest, cleanest answer.
H.B. thanks again and as for the hyperlink, this is still in development, it's not going to be in anyway a hyperlink, just some custom menu button with some animation so it's not so boring for the user :P
Your Label.Template no longer links the Content property of the Label (which you set to "Create") to any internal part. To fix this you can for example bind the TextBlock.Text like this:
<ControlTemplate TargetType="Label">
<TextBlock Style="{StaticResource TextBlockStyle}"
Text="{TemplateBinding Content}"/>
</ControlTemplate>
(I just noticed that you make the Label look like a hyperlink, you do realize that there already is a class for that, right?)
If I have the following style defined:
<UserControl.Resources>
<Style TargetType="TextBlock" x:Key="ProblemStyle">
<Setter Property="FontSize" Value="40"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</UserControl.Resources>
Then when I have a ContentPresenter data bound to a string, in WPF I can get it to style the text as required with the following XAML:
<ContentPresenter Content="{Binding Problem}">
<ContentPresenter.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource ProblemStyle}" />
</ContentPresenter.Resources>
</ContentPresenter>
However, in Silverlight, this doesn't work. Is there a way that works for both?
Use the TextElement Attached property. You will not be able to set a style, but most of the properties that effects the Textblock are there..
<ContentPresenter x:Name="ContentPresenter"
ContentSource="Header"
HorizontalAlignment="Left"
TextElement.FontFamily="Segoe UI"
TextElement.FontSize="12"
TextElement.FontWeight="Bold"
TextElement.Foreground="White"
RecognizesAccessKey="True" />
First:
Make sure that your style "ProblemStyle" is being loaded before the application tries to render the ContentPresenter. In Silverlight, the order the styles are defined makes a difference, and if it has not been loaded first then it may not be reading anything.
Ok, I am going to run on some assumptions here, the first one being that you are using a ContentControl to display something and that the ContentPresenter is inside of this control.
But why not create a Style for the ContentControl?
<Style x:key="ProblemStyle" TargetType="ContentControl">
<Setter Property="FontSize" Value="40"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
Then your ContentControl would have the Style set to the StaticResource of "ProblemStyle".
Since by default the template of a ContentControl has the ContentPresenter - or you can define the ContentPresenter template in the style as well:
<Style x:key="ProblemStyle" TargetType="ContentControl">
<Setter Property="FontSize" Value="40"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The template there is just as a placeholder to give an idea of where it would/could be located.