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.
Related
I'm wondering if WPF offers a way to change the style of a named element defined inside a ControlTemplate, from a style declared somewhere else, as illustrated in the example below.
Lets redefine the ControlTemplate of a Label with a TextBlock named «MyTextBlock»
<Style x:Key="MyLabel" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock x:Name="MyTextBlock"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Lets inherit the style of the previously defined Label
<Style x:Key="MyNewLabel" BasedOn="{StaticResource MyLabel}">
<Setter Property="{Binding {[SOME.EXPRESSION.TO.REACH.MyTextBlock???]}, Path=Foreground}" Value="Red" />
</Style>
Regards
I'm wondering if WPF offers a way to change the style of a named element defined inside a ControlTemplate, from a style declared somewhere else
Short answer: No.
You cannot access or set a property of the element (TextBlock) directly but you may set a property of the styled control (Label) that you bind to the element in the template, e.g.:
<Style x:Key="MyLabel" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock x:Name="MyTextBlock" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MyNewLabel" TargetType="Label" BasedOn="{StaticResource MyLabel}">
<Setter Property="Foreground" Value="Red" />
</Style>
I've tried all kinds of template binding and such to get this to work, but if I use this style on a control, the internal textbox control doesn't show focus.
I'm doing this because I want to set an error template that wraps around the textbox and the spot reserved for displaying units.
Now, typing in the box correct updates the text inside. And clicking on it will show the highlighted border and input caret, but tabbing into it won't.
<Style x:Key="Special" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<DockPanel
LastChildFill="True"
Visibility="Visible">
<Border
Name="PART_UnitContainer"
DockPanel.Dock="Right"
Visibility="Collapsed">
<Label
Content="ft"
Style="{DynamicResource UnitLabel}"
/>
</Border>
<TextBox Name="PART_Control" Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="PART_UnitContainer" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Initially I set the whole control as no tab stop, and internal one with tabstop, but apparently you also have to set the tab navigation to continue. I didn't when I tried playing with navigation, so I overlooked this setting.
<Style x:Key="Special" TargetType="{x:Type TextBox}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<ControlTemplate>
...
<Text IsTabStop="True" Name="PART_Control" ...
...
</ControlTemplate>
</Setter>
</Style>
However, this little trick doesn't work for shift-tab out of an editable combobox. I'll update the answer if I figure it out.
For comboboxes you have to do it differently. You don't set TabNavigation to Continue, and you don't set IsTabStop on internal combobox to true.
See
<Style x:Key="Special" TargetType="{x:Type ComboBox}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<ControlTemplate>
...
<ComboBox Name="PART_Control" ...
...
</ControlTemplate>
</Setter>
</Style>
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 have a UI in Silverlight with some borders, and with a TextBlock inside that borders. There will be other TextBlocks outside borders.
<Border>
<TextBlock>This text should be centered</TextBlock>
</Border>
<Border>
<TextBlock>This one too</TextBlock>
</Border>
<TextBlock>this one shouldn't</TextBlock>
What I'm trying to achieve is to format all TextBlock's inside a Border, without having to set the style in every TextBlock. If it was CSS , it will be something like that : .border .textBlock { (...) }
I know i can set a style inside the scope of a border:
<Border>
<Border.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource DefaultTextBlockStyle}">
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
</Style>
</Border.Resources>
<TextBlock>Centered Text</TextBlock>
</Border>
But I would still need to set this to every border in my page. So now i presente the question, can i set in a style, in order to set it one time to affect all Borders? I tried the code bellow, but it didn't work. It didn't give me any errors, but it didn't affect the TextBlock formatting either.
<Style TargetType="Border">
<Setter Property="Resources">
<Setter.Value>
<ResourceDictionary>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</ResourceDictionary>
</Setter.Value>
</Setter>
</Style>
Try this:
<Style TargetType="Border">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
This works in WPF. In Silverlight I am afraid you cannot do this though.
Here is the XAML in my application resources that globally changes all of the Button controls in the application to look and behave like I want:
<Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" CornerRadius="0" BorderThickness="0"
Background="CornflowerBlue" BorderBrush="CornflowerBlue">
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<!-- a bunch o' triggers here -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
On one of my application's user controls, I would like to change some properties of this button. Here is some XAML that I am using in the UserControl.Resources section now to do this:
<Style x:Key="SpecialButton" TargetType="Button" BasedOn="{StaticResource MyButtonStyle}">
<Setter Property="Width" Value="20" />
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="Content" Value=">" />
<Setter Property="Border" Value="#eeeeee" />
<Setter Property="Border.Background" Value="#eeeeee" />
</Style>
The Button controls on my UserControl that I assign the style to of SpecialButton have the correct width, visibility, and content, but these last two attempts do not work. How would I go about changing the background color of the Border with a name of "Border" from the application resource in this SpecialButton style?
What you can do is use TemplateBinding to set the Background property on the control, in the base style. Also in the base style, set the Background color to the default "CornflowerBlue".
<Setter Property="Background" Value="CornflowerBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border" Background="{TemplateBinding Background}"
Now you can overwrite the Background in the derived style:
<Style x:Key="SpecialButton" TargetType="Button" BasedOn="{StaticResource MyButtonStyle}">
<Setter Property="Background" Value="#eeeeee" />
(Note that, if you want to use other properties that aren't defined on the Button control -- or, say you wanted to use multiple background colors -- then you'd have to create your own control that inherits Button, and expose the new properties as Dependency Properties.)