Silverlight apply implicit style that sets other style - c#

I have a TextBox Style with a Key defined in external resource dictionary file, then I'm trying to define a new implicit TextBox Style that sets "Keyed" style from resource dictionary, so basically I want to seet the style from resource dictionary as a default for TextBox, but I can't remove Key from there, because it is used by other code.
<ResourceDictionary Source="FileWithNiceTextBoxStyle.xaml"/>
<Style TargetType="TextBox">
<Setter Property="Style" Value="{StaticResource NiceTextBoxStyle}"/>
</Style>
However this doesn't work, and result in Visual Studio crash.

Use the BasedOn attribute:
<Style TargetType="TextBox" x:Key="GlobalTextBox">
<Setter Property="Background" Value="Pink"/>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource GlobalTextBox}"></Style>
...
<TextBox Text="I have pink background"/>

Related

Default style lost (e.g. colors) after setting custom style

I use the RadTreeView from telerik to show a tree with nodes. To bind the IsExpanded Property to my own IsExpanded property I use the following snippet:
<Style TargetType="{x:Type telerik:RadTreeViewItem}" x:Key="ItemContainerStyle"  >
    <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}"/>
</Style>
This works fine so far but the highlight color of the nodes turned from blue into grey. How can I keep the original style and only add the setter property?
EDIT:
I use the telerik Windows8Theme and adjust the Windows8Palette.
Before adding the mentioned style element in XAML the color of a selected element was the AccentColor (blue) of the Windows8Palette. After adding the style element it seems to use the BasicColor (grey) of the Windows8Palette. I don't know what exactly is going on but comparing the RGB values shows this color switch.
You need to inherit the style from the default:
<Style x:Key="ItemContainerStyle"
TargetType="{x:Type telerik:RadTreeViewItem}"
BasedOn="{x:Type telerik:RadTreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}"/>
</Style>
The BasedOn="{x:Type telerik:RadTreeViewItem}" does tell it to inherit the current default style and just "add" your setter.
It should be:
<Style x:Key="ItemContainerStyle" TargetType="{x:Type telerik:RadTreeViewItem}" BasedOn="{StaticResource {x:Type telerik:RadTreeViewItem}}">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}"/>
</Style>
...if you want to base your custom style on the default one.
I finally got the answer. I overwrote our custom style from another assembly. This here works:
<telerik:radGridView.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/OtherAssembly,component/existingStyles.xaml />
    </ResourceDictionary.MergedDictionaries>
    <Style BasedOn="{StaticResource xKeyOfStyleToExtendFromExistingStyles}" TargetType="{x:Type telerik:RadTreeViewItem}">
    <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}"/>
</Style>
  </ResourceDictionary>
</telerik:radGridView.Resources>

Override dictionary style with local style

I have a user control (a modernTab, provded by modernui) that has a style applied to it, as is specified in a resource dictionary (that again came with modernui).
That's fine, styling for this app is provided through some default resources in the App.xaml file that look like this:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
</ResourceDictionary.MergedDictionaries>
That's well and good. However, I want to override the link style I am using for a specific instance of a modernTab. So in my XAML, I'm trying to do it like this:
<mui:ModernTab ListWidth="Auto"
Layout="List"
Links ="{Binding MyViewModelLinks}">
<mui:ModernTab.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="Yellow" />
</Style>
</mui:ModernTab.Resources>
</mui:ModernTab>
Now, I know from looking at the source that down inside the guts of a modernTab control it's got a bunch of ListBoxItems - these are what I want to change the style on.
What I don't get is why my "local" style isn't going down and overriding for this specific instance. Any ideas?
I tried defining my style override in App.xaml (even though I don't really want it to be global) and it didn't work. Clearly I'm missing something.
What you are doing here is not overriding default style of ModernTab but specifying resources of a particular instance, the style is still taken from ModernTab.xaml
What you need to do here is to specify inline style for your instance of ModernTab:
<mui:ModernTab ...>
<mui:ModernTab.Style>
<Style TargetType="mui:ModernTab">
<!------- Full ModernTab Style ----->
</Style>
</mui:ModernTab.Style>
This inline style will override the default. The bad news is that you cannot create a style based on default ModernTab style and just tweak small details because the default style does not have a name (x:Key). But you can copy the whole style, change whatever you want in it, and use it instead. You should probably put it in a resource file and then use it on your ModernTab instance like this:
<mui:ModernTab Style={StaticResource MyAwesomeStyle} .../>
Hope this helps
You need to "override" the ItemContainerStyle of the ListBox in the ModernTab. This should do the trick:
<mui:ModernTab ListWidth="Auto"
Layout="List"
Links ="{Binding MyViewModelLinks}">
<mui:ModernTab.Resources>
<Style TargetType="ListBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="Yellow" />
</Style>
</Setter.Value>
</Setter>
</Style>
</mui:ModernTab.Resources>
</mui:ModernTab>

General WPF Rendering Rules (Multiple styles on same target type)

Relating on this question (Multiple styles on same target type) i have another point concerning the general wpf styling rules.
As mentioned in one of the answers above, wpf applies the closest style definition to the control when no x:key is specified. (also applies to styles with the same key; given the fact that we have the same key here: the control type)
My question:
What if we have two same-named styles in different resource dictionaries that are both equal close and accessible to the control?
Compared to CSS you have two definitions for i.e. an a-element. In CSS same style properties are getting overriden by the last definition while different properties are merged into one logical style definition.
Does WPF behave the same or does it prefer one whole style-resource with all its properties while avoiding the other one completely?
And if the latter how does it decide to apply one or the other.
Update
dict1.xaml:
<ResourceDictionary>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="BorderBrush" Value="SomeValue1" />
<Setter Property="Background" Value="SomeValue2" />
<Setter Property="FontSize" Value="SomeValue3" />
</Style>
</ResourceDictionary>
dict2.xaml:
<ResourceDictionary>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="BorderBrush" Value="SomeValue4" />
<Setter Property="Foreground" Value="SomeValue5" />
</Style>
</ResourceDictionary>
SomeView.xaml:
...
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="path/dict1.xaml" />
<ResourceDictionary Source="path/dict2.xaml" />
</ResourceDictionary.MergedDictionaries>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="FontSize" Value="SomeValue6" />
</Style>
</Grid.Resources>
<Button /><!--THIS IS THE CONTROL THAT MATTERS-->
</Grid>
...
I think for FontSize its simple, it applies SomeValue6 because its the closest style definition. But what about BorderBrush. Both Dictionaries are equally close to the Button and are both accessible.
And What about Background and Foreground? Does it merge both style definitions to something like this:
<ResourceDictionary>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="BorderBrush" Value="SomeValue4" />
<Setter Property="Background" Value="SomeValue2" />
<Setter Property="Foreground" Value="SomeValue5" />
<Setter Property="FontSize" Value="SomeValue6" />
</Style>
</ResourceDictionary>
Of course the chaos is much bigger when you include cross-assembly dictionaries, that depend on each other and you are seeking where the actual style comes from.
This code example isn't working because of the merged dictionary and its hard to isolate the exact behavior because my actual application is really chaotic like I described.
So I want to know the official rules intended by Microsoft that should be basic for every developer. But I didnt find anything in the docs.

Add ErrorTemplate to a MahApp control without overwriting its default style

I am using MahApps and working on implementing validation for TextBoxes. MahApps provides some nice properties in TextBoxes, as Controls:TextBoxHelper.Watermark and Controls:TextBoxHelper.ClearTextButton. I am writing an ErrorTemplate using my style but I overwrite the default template of the TextBox and lose those Metro properties. How can I achieve my goal without losing the template:
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ErrorToolTipTemplate}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
You should define your new style based on existing to keep everything it has. I guess in case of MahApps it will be MetroTextBox:
<Style TargetType="TextBox" BasedOn="{StaticResource MetroTextBox}">
<!-- your properties go here -->
</Style>
The BasedOn is the key to success. However, it's likely, that you're using MahApps controls not in just one place. Therefore, try to make your style more generic and avoid direct references to MetroTextBox resource in the BasedOn.
The more good looking XAML style would be like that:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<!-- your properties go here -->
</Style>

Unset a value in a custom Style?

I my WPF application I'd like to change the text color by setting Foreground on the main Window like
<Window Foreground="Red">
<TextBlock Text="Hello World" />
</Window>
This works fine for TextBlocks, but if I add a Button, the font there stays black, since Button has a Setter for Foreground in its default style. can I make a new default style for Button based on the original one, but removing the Foregound setter?
I haven't tested this, but you could try using a base style in an appropriate resource collection (e.g. at the application level in App.xaml), and then create an implicit style for each type of control based on this base style.
<Style TargetType="{x:Type Control}" x:Key="DefaultControlStyle">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultControlStyle}" />
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource DefaultControlStyle}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource DefaultControlStyle}" />
<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource DefaultControlStyle}" />
You could also use a relative source binding trick described here.

Categories

Resources