I Have this very simple xaml style problem in Silverlight4.
When I set a style on element through explicit styling my implicit style is removed?
I created a simple example to illustrate the problem.
<UserControl.Resources>
<Style TargetType="TextBox">
<Setter Property="Background" Value="red"/>
</Style>
<Style TargetType="FrameworkElement" x:Key="test">
<Setter Property="Margin" Value="20"/>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<TextBox Style="{StaticResource test}" Height="40" Width="120"> </TextBox>
</Grid>
</UserControl>
So when I remove the Style="{StaticResource test}
the implicit style is applied again.
Note: this is oversimplified example. So moving the margin to the texbox style is not an option because the real project contains larger xaml styling.
Does somebody know a solution or can confirm that this isn't possible?
Thx in advance!
Take a look at the BasedOn style property. This will allow you to inherit from a base style, to use the base properties and add some changes.
Now, there is a problem with BasedOn - it can't be used with an implicit style. However, this is pretty easy to work around. This article demonstrates the work around and will also explain the BasedOn property a bit better:
Silverlight how-to: Inherit from an Implicit Style
Related
I have text block with MaxWidth="80" and want change on Style without remove MaxWidth="80"
the TextBlock is at third party control
for sample:
<Window.Resources>
<Style TargetType="TextBox" >
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontSize" Value="10"/>
</Style>
</Window.Resources>
<Grid>
<TextBox FontSize="45" Foreground="Blue" Text="OH My God"/>
</Grid>
Not sure i'm answering what you asked, since, as other users pointed out, the question is not well written. But...
A setter within a style has less priority than setting the property directly on the instance of the object.
So, even though your style declares
<Setter Property="MaxWidth" Value="80"/>
If you write your textblock/textbox like this
<TextBlock MaxWidth="100"/>
the 100 will prevail on the 80, thus the max width will be 100.
In the WPF there is a strict rule which property is about to be used.
So you can:
Define a default style with the property = 100.
Define another style based on the default and override the property as you wish.
Apply the new created style to your TextBox.
And attribute has more power than a style.
i am trying to override the wpf toolkit propertygrid's style. Therefore i modified the generic.xaml.
Now i have the problem that the defaulteditors styles are not overridden.
Therefore i wrote following style to override the PropertyGridEditorComboBox in Xaml:
<Style TargetType="{x:Type xctk:PropertyGridEditorComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ComboBox SelectedItem="{Binding Value}" ItemsSource="{?????}" />
</ControlTemplate>
</Setter.Value>
</Setter>
This snippet seems to work except the fact that i do not know what i have to bind as an itemssource. What do i have to bind as Itemssource?
If there is also a better way to override the DefaultEditors appearance please let me know.
KR Manuel
You have to reach from the style to the control it's applied to -- something like this:
ItemsSource="{TemplateBinding ItemsSource}"
(Assuming that PropertyGridEditorComboBox has an ItemsSource property.)
The stuff that does work
I need to style controls of a certain type that are children of a StackPanel. I'm using:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">...</Style>
</StackPanel.Resources>
<TextBlock ...>
...
</StackPanel>
And this works fine! Each TextBlock looks to the resources of it's parent (the StackPanel) to find out how it should be styled. It doesn't matter how far down you nest the TextBlock down a StackPanel... if it doesn't find a style in its direct parent, it will look at its parent's parent and so on, until it finds something (in this case, the style that was defined in ).
The stuff that doesn't work
I ran into a problem when I nested a TextBlock inside a ContentControl, which had a Template (see code below). The ControlTemplate seems to disrupt the way a TextBlock retrieves its style from its parents, grandparents,...
The use of a ControlTemplate effectively seems to knock out cold the TextBlock's means of finding its rightful style (the one in StackPanel.Resources). When it encounters a ControlTemplate, it stops looking for its style in the resources up the tree, and instead defaults to the style in MergedDictionaries of the Application itself.
<StackPanel Orientation="Vertical" Background="LightGray">
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
</StackPanel.Resources>
<TextBlock Text="plain and simple in stackpanel, green" />
<ContentControl>
<TextBlock Text="inside ContentControl, still green" />
</ContentControl>
<ContentControl>
<ContentControl.Template>
<ControlTemplate TargetType="{x:Type ContentControl}">
<StackPanel Orientation="Vertical">
<ContentPresenter />
<TextBlock Text="how come this one - placed in the template - is not green?" />
</StackPanel>
</ControlTemplate>
</ContentControl.Template>
<TextBlock Text="inside ContentControl with a template, this one is green as well" />
</ContentControl>
</StackPanel>
Is there a way - besides duplicating the Style in StackPanel.Resources to ControlTemplate.Resources - to make the TextBlock inside that ControlTemplate find the defined style?
Thanks...
WPF considers ControlTemplates to be a boundry, and will not apply implicit styles (styles without an x:Key) inside of templates.
But there is one exception to this rule: anything that inherits from Control will apply implicit styles.
So you could use a Label instead of a TextBlock, and it would apply the implicit style defined further up your XAML hierarchy, however since TextBlock inherits from FrameworkElement instead of Control, it won't apply the implicit style automatically and you have to add it manually.
My most common way to get around this is to add an implicit style in the ControlTemplate.Resources that is BasedOn the existing implicit TextBlock style
<ControlTemplate.Resources>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource {x:Type TextBlock}}" />
<ControlTemplate.Resources>
Other common ways of getting around this are:
Place the implicit style in <Application.Resources>. Styles placed here will apply to your entire application, regardless of template boundaries. Be careful with this though, as it will apply the style to TextBlocks inside of other controls as well, like Buttons or ComboBoxes
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
</Application.Resources>
Use a Label instead of a TextBlock since it's inherited from Control, so will apply implicit Styles defined outside the ControlTemplate
Give the base style an x:Key and use it as the base style for an implicit TextBlock styles inside the ControlTemplate. It's pretty much the same as the top solution, however it's used for base styles that have an x:Key attribute
<Style x:Key="BaseTextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
...
<ControlTemplate.Resources>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource BaseTextBlockStyle}" />
<ControlTemplate.Resources>
<Window x:Class="AiweeeTest.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">
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="backcolorType" Color="Red"></SolidColorBrush>
<SolidColorBrush x:Key="forecolorType" Color="Green"></SolidColorBrush>
<Style x:Key="TextboxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Yellow"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" Value="{StaticResource backcolorType}"/>
<Setter Property="Foreground" Value="{StaticResource forecolorType}"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<TextBox Name="textbox1" Width="100" Height="25" Style="{StaticResource TextboxStyle}" IsEnabled="False"/>
</Grid>
</Window>
I am not able to update the background of a textbox using the trigger defined above, however when I copy the entire textbox control template template and replace the "DisabledBackgroundBrush" with my own color it does. What's the difference, I've already seen some links over this matter; however I am not able to understand the reason behind it. As I understand, Triggers are fired in the order they are defined, then the trigger defined locally in the window should be able to override the background color of the textbox when disabled. Please clarify.
PS: I am not trying to achieve anything special here, but just want to understand why is this so. This gives me a bit of frustration of WPF not being intuitive for situations like such.
I am guessing it has something to do with the order in which WPF will apply values for a DependencyProperty. This MSDN article has some good information on Dependency Property Precedence
Basically the order goes:
Property system coercion
Active animations, or animations with a Hold behavior.
Local value
TemplatedParent template properties
Triggers from the TemplatedParent template
Property sets (typically through XAML attributes) in the TemplatedParent template
Implicit style
Style triggers
Template triggers
Style setters
Default (theme) style
Active triggers in the theme style
Setters in the theme style
Inheritance
Default value from dependency property metadata
This question is very similar to Change WPF DataTemplate..., which I have read and implemented. It worked beautifully at first, but I ran into a problem with it.
That problem is that, when using themes in your application such as those in the WPF Futures project (e.g. Expression Dark), the ListBoxItems all revert back to the default WPF styling. This breaks the theme for those elements and, for example, produces black text on black background where the text would otherwise be white. This also affected my TreeView, and presumably would affect other similar controls.
I think this is because conflicting styles are being set for ListBox.ItemContainerStyle--one from the theme and one for switching data templates.
I've looked around for other solutions, but haven't found anything yet. Here are the leads or ideas I've had so far:
Subclassing DataTemplateSelector and setting it to ListBox.ItemTemplateSelector. (The current best bet).
Somehow, somewhere use a Trigger, DataTrigger, or EventTrigger.
Give up on themes.
Somehow hack the functionality I want into the theme.
Somehow make my custom ItemContainerStyle somehow inherit it's colors and eye candy from the theme's style. (I tried it briefly, and it didn't work.)
Here is my ListBox and related pieces:
<Window.Resources>
<DataTemplate x:Key="NormalTemplate">
...
</DataTemplate>
<DataTemplate x:Key="SelectedTemplate">
...
</DataTemplate>
</Window.Resources>
<ListBox x:Name="RegisterListBox" Grid.Row="0"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Adjustments}">
<!-- this is from the post referenced above -->
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate" Value="{StaticResource NormalTemplate}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
The Listbox.DataContext is set in code to enable the ItemsSource binding.
Any ideas how I can achieve the kind of functionality described above while maintaining seamless support for themes?
Have you tried doing something like this?
<ListBox.ItemContainerStyle>
<Style
TargetType="{x:Type ListBoxItem}"
BasedOn="{StaticResource {x:Type ListBoxItem}}"> <=====
...
The idea is that the framework will first go look for a style with a key equal to typeof(ListBoxItem), it will find it in the themes, and then your style will just extend the themed one with your specific details.