Is there any way to combine mutliple styles in XAML to make a new style that has all of the desired settings?
For example (pseudo code);
<Style x:key="A">
...
</Style>
<Style x:key="B">
...
</Style>
<Style x:key="Combined">
<IncludeStyle Name="A"/>
<IncludeStyle Name="B"/>
... other properties.
</Style>
I know that there is a BasedOn property for styles, but that feature will only take you so far. I am really just looking for an easy way (in XAML) to create these 'combined' styles. But like I said before, I doubt it exists, unless anyone has heard of such a thing??
You can make a custom markup extensions that will merge styles properties and triggers into a single style. All you need to do is add a MarkupExtension-derived class to your namespace with the MarkupExtensionReturnType attribute defined and you're off and running.
Here is an extension that will allow you to merge styles using a "css-like" syntax.
MultiStyleExtension.cs
[MarkupExtensionReturnType(typeof(Style))]
public class MultiStyleExtension : MarkupExtension
{
private string[] resourceKeys;
/// <summary>
/// Public constructor.
/// </summary>
/// <param name="inputResourceKeys">The constructor input should be a string consisting of one or more style names separated by spaces.</param>
public MultiStyleExtension(string inputResourceKeys)
{
if (inputResourceKeys == null)
throw new ArgumentNullException("inputResourceKeys");
this.resourceKeys = inputResourceKeys.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (this.resourceKeys.Length == 0)
throw new ArgumentException("No input resource keys specified.");
}
/// <summary>
/// Returns a style that merges all styles with the keys specified in the constructor.
/// </summary>
/// <param name="serviceProvider">The service provider for this markup extension.</param>
/// <returns>A style that merges all styles with the keys specified in the constructor.</returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
Style resultStyle = new Style();
foreach (string currentResourceKey in resourceKeys)
{
object key = currentResourceKey;
if (currentResourceKey == ".")
{
IProvideValueTarget service = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
key = service.TargetObject.GetType();
}
Style currentStyle = new StaticResourceExtension(key).ProvideValue(serviceProvider) as Style;
if (currentStyle == null)
throw new InvalidOperationException("Could not find style with resource key " + currentResourceKey + ".");
resultStyle.Merge(currentStyle);
}
return resultStyle;
}
}
public static class MultiStyleMethods
{
/// <summary>
/// Merges the two styles passed as parameters. The first style will be modified to include any
/// information present in the second. If there are collisions, the second style takes priority.
/// </summary>
/// <param name="style1">First style to merge, which will be modified to include information from the second one.</param>
/// <param name="style2">Second style to merge.</param>
public static void Merge(this Style style1, Style style2)
{
if(style1 == null)
throw new ArgumentNullException("style1");
if(style2 == null)
throw new ArgumentNullException("style2");
if(style1.TargetType.IsAssignableFrom(style2.TargetType))
style1.TargetType = style2.TargetType;
if(style2.BasedOn != null)
Merge(style1, style2.BasedOn);
foreach(SetterBase currentSetter in style2.Setters)
style1.Setters.Add(currentSetter);
foreach(TriggerBase currentTrigger in style2.Triggers)
style1.Triggers.Add(currentTrigger);
// This code is only needed when using DynamicResources.
foreach(object key in style2.Resources.Keys)
style1.Resources[key] = style2.Resources[key];
}
}
Your example would then be solved by going:
<Style x:key="Combined" BasedOn="{local:MultiStyle A B}">
... other properties.
</Style>
We have defined a new style named "Combined" by merging two other styles "A" and "B" within the built-in BasedOn attribute (used for style inheritance). We can optionally add other properties to the new "Combined" style as per usual.
Other Examples:
Here, we define 4 button styles, and can use them in various combinations with little repetition:
<Window.Resources>
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="Width" Value="120" />
<Setter Property="Height" Value="25" />
<Setter Property="FontSize" Value="12" />
</Style>
<Style TargetType="Button" x:Key="GreenButtonStyle">
<Setter Property="Foreground" Value="Green" />
</Style>
<Style TargetType="Button" x:Key="RedButtonStyle">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style TargetType="Button" x:Key="BoldButtonStyle">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Window.Resources>
<Button Style="{local:MultiStyle ButtonStyle GreenButtonStyle}" Content="Green Button" />
<Button Style="{local:MultiStyle ButtonStyle RedButtonStyle}" Content="Red Button" />
<Button Style="{local:MultiStyle ButtonStyle GreenButtonStyle BoldButtonStyle}" Content="green, bold button" />
<Button Style="{local:MultiStyle ButtonStyle RedButtonStyle BoldButtonStyle}" Content="red, bold button" />
You can even use the "." syntax to merge the "current" default style for a type (context-dependent) with some additional styles:
<Button Style="{local:MultiStyle . GreenButtonStyle BoldButtonStyle}"/>
The above will merge the default style for TargetType="{x:Type Button}" with the two supplemental styles.
Credit
I found the original idea for the MultiStyleExtension at bea.stollnitz.com and modified it to support the "." notation to reference the current style.
You can use BasedOn property in style, for example:
<Style x:Key="BaseButtons" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="Cursor" Value="Hand"></Setter>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</Style>
<Style x:Key="ManageButtons" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtons}">
<Setter Property="Height" Value="50"></Setter>
<Setter Property="Width" Value="50"></Setter>
</Style>
<Style x:Key="ManageStartButton" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtons}">
<Setter Property="FontSize" Value="16"></Setter>
</Style>
and use:
<Button Style="{StaticResource ManageButtons}"></Button>
<Button Style="{StaticResource ManageStartButton}"></Button>
Related
I created a custom user control called FlatButton deriving from Button:
XAML:
<Button
x:Class="Program.GUI.Controls.FlatButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:GUIControls="clr-namespace:Program.GUI.Controls"
mc:Ignorable="d">
<Button.Resources>
<ResourceDictionary>
<Style x:Key="{x:Type GUIControls:FlatButton}" TargetType="{x:Type GUIControls:FlatButton}" BasedOn="{StaticResource ResourceKey={x:Type Button}}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GUIControls:FlatButton}">
<Grid x:Name="LayoutRoot" Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
<TextBlock
x:Name="Text"
Text="{TemplateBinding Content}"
Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverBackground}"/>
<Setter TargetName="Text" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverForeground}"/>
</Trigger>
<Trigger Property="IsMouseCaptured" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ClickBackground}"/>
<Setter TargetName="Text" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ClickForeground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Button.Resources>
</Button>
CS:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Program.GUI.Controls {
/// <summary>
/// Interaction logic for FlatButton.xaml
/// </summary>
public partial class FlatButton : Button {
public static readonly DependencyProperty HoverBackgroundProperty = DependencyProperty.Register(
"HoverBackground",
typeof(Brush),
typeof(FlatButton)
);
public static readonly DependencyProperty HoverForegroundProperty = DependencyProperty.Register(
"HoverForeground",
typeof(Brush),
typeof(FlatButton)
);
public static readonly DependencyProperty ClickBackgroundProperty = DependencyProperty.Register(
"ClickBackground",
typeof(Brush),
typeof(FlatButton)
);
public static readonly DependencyProperty ClickForegroundProperty = DependencyProperty.Register(
"ClickForeground",
typeof(Brush),
typeof(FlatButton)
);
public Brush HoverBackground { get; set; }
public Brush HoverForeground { get; set; }
public Brush ClickBackground { get; set; }
public Brush ClickForeground { get; set; }
static FlatButton() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatButton), new FrameworkPropertyMetadata(typeof(FlatButton)));
}
public FlatButton() {
this.InitializeComponent();
}
}
}
The Problem is when I try to create an extending style the base style is not found:
MainWindow XAML:
<Style x:Key="DefaultDarkButtonThemeStyle" TargetType="{x:Type GUIControls:FlatButton}" BasedOn="{StaticResource {x:Type GUIControls:FlatButton}}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{DynamicResource ColorTextPrimaryDark}"/>
<Setter Property="HoverBackground" Value="{DynamicResource ColorPrimaryDarkLight}"/>
<Setter Property="HoverForeground" Value="{DynamicResource ColorTextPrimaryDarkLight}"/>
<Setter Property="ClickBackground" Value="{DynamicResource ColorPrimaryDarkLightLight}"/>
<Setter Property="ClickForeground" Value="{DynamicResource ColorTextPrimaryDarkLightLight}"/>
</Style>
Exception:
System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.' Line number '45' and line position '47'.'
Inner Exception
Exception: Cannot find resource named 'Program.GUI.Controls.FlatButton'. Resource names are case sensitive.
If you develop a custom control like FlatButton, you should create a separate style that either resides in a theme resource dictionary (e.g. Themes/Generic.xaml) if you develop a custom control library or any other dedicated resource dictionary. Regardless of which path you choose, you can merge the corresponding resource dictionary into the application resources or any other resource dictionary on a lower scope in order to make the style accessible within that scope (apply it automatically if it is implicit or creating styles based on it, whatever).
Your partial XAML definition is the usual approach for creating UserControls, but not for custom controls. The style for FlatButton in the resources of the Button markup can only be resolved within the scope of this local resource dictionary, which means the FlatButton itself or down its visual tree. Look at the static resource lookup behavior to understand how the style is being resovled and why it fails.
The lookup process checks for the requested key within the resource dictionary defined by the element that sets the property.
The lookup process then traverses the logical tree upward to the parent element and its resource dictionary. This process continues until the root element is reached.
App resources are checked. App resources are those resources within the resource dictionary that is defined by the Application object for your WPF app.
Consequently, when your DefaultDarkButtonThemeStyle is created in your main window and tries to resolve the GUIControls:FlatButton base style, it does not find it, because it is not defined within the window resources or anywhere up the visual tree or the application resources.
However, if you simply created a theme or regular resource dictionary that contained the style and included it in the window or application resource, it would be resolved successfully.
For more information on creating custom controls, including how to set up styles and resource dictionaries, you can refer to Control authoring overview.
I've got a DataGrid control in my WPF application that contains an object. There is a boolean property of that object which can be changed by user actions. I need the style of the row to change when that property's value changes.
I have written a class that descends from StyleSelector:
public class LiveModeSelector : StyleSelector {
public Style LiveModeStyle { get; set; }
public Style NormalStyle { get; set; }
public override Style SelectStyle( object item, DependencyObject container ) {
DataGridRow gridRow = container as DataGridRow;
LPRCamera camera = item as LPRCamera;
if ( camera != null && camera.IsInLiveMode ) {
return LiveModeStyle;
}
return NormalStyle;
}
}
The View Model class in question implements INotifyPropertyChanged, and it raises the PropertyChanged event when the property in question changes.
// Note: The ModuleMonitor class implements INotifyPropertyChanged and raises the PropertyChanged
// event in the SetAndNotify generic method.
public class LPRCamera : ModuleMonitor, ICloneable {
. . .
public bool IsInLiveMode {
get { return iIsInLiveMode; }
private set { SetAndNotify( "IsInLiveMode", ref iIsInLiveMode, value ); }
}
private bool iIsInLiveMode;
. . .
/// </summary>
public void StartLiveMode() {
IsInLiveMode = true;
. . .
}
public void StopLiveMode() {
IsInLiveMode = false;
. . .
}
}
The value of the property is changed when the user performs the required action, but the style doesn't change.
I have placed a breakpoint in the SelectStyle method and I see the breakpoint gets hit when the control is first loaded, but it does not get hit when the property's value changes.
What am I missing?
I found a way to do this that grew out of #Rachel's answer to my question. However, the code details differ somewhat and I want to show exactly what works.
The first step was to combine the two different Styles into one for the DataGridRow class:
<Style TargetType="DataGridRow" x:Key="CameraStyle">
<Setter Property="Foreground" Value="{DynamicResource TextForeground}" />
<Setter Property="Background" Value="{DynamicResource DataBackground}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsInLiveMode}" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Background" Value="Yellow" />
</DataTrigger>
</Style.Triggers>
</Style>
The second step was to set the DataGrid control's RowStyle property to this new style:
<DataGrid . . .
RowStyle={StaticResource CameraStyle}">
. . .
</DataGrid>
This works. The foreground and background of the row changes when the user puts the LPRCamera associated with that row into Live Mode and changes back to normal when they take it out of Live Mode, which is what I was going for.
Thanks #Rachel!
I don't think a StyleSelector listens for PropertyChange notifications, so it doesn't get re-run when the IsInLiveMode property gets changed.
Put your style in a DataTrigger based on IsInLiveMode instead, and it will get re-evaluated anytime the property change notification gets raised.
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}" x:Key="Style1">
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="{x:Type DataGridRow}" x:Key="Style2">
<Setter Property="Background" Value="Blue" />
</Style>
</DataGrid.Resources>
<DataGrid.Style>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="RowStyle" Value="{StaticResource Style1}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyDataGrid, Path=DataContext.IsInLiveMode}" Value="True">
<Setter Property="RowStyle" Value="{StaticResource Style2}" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Style>
I am using the RibbonControlsLibrary (.Net 4.0) for my ribbons. My implementation is completely realized using MVVM.
Now I like to use the benefit of the resizing feature. But I can't set the reduction order of the group boxes. This is because I have to define the names of the group boxes in a special order. I can't set the names of the group boxes, because I am using data templates.
I tried to bind the name of the ribbon group box user controls to a property on the datacontext, but as I supposed this doesn't work.
So, do I have any chance to set the ribbon group box user control names to a property of the data context?
Setting the RibbonGroups' names
There may be others solutions, mine is to implement a Behavior that sets the RibbonGroup's name in the OnAttached method.
public class RibbonGroupNameBehavior : Behavior<RibbonGroup>
{
protected override void OnAttached()
{
base.OnAttached();
GroupeCommandesViewModel groupeCommandesViewModel = this.AssociatedObject.DataContext as GroupeCommandesViewModel;
if (groupeCommandesViewModel != null)
{
this.AssociatedObject.Name = groupeCommandesViewModel.Nom;
}
}
}
You may want to add a try-catch block around the assignment...
Using the behavior
As you are using DataTemplates, I think you'll have to assign the behavior to the RibbonGroups with a Style.
I have been using this solution with success.
As you'll see, my behavior's code does not provide the required dependency property, you'll have to add it.
Here is my shortened Ribbon's style :
<r:Ribbon.Style>
<Style TargetType="{x:Type r:Ribbon}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type r:RibbonTab}">
<Setter Property="ItemsSource" Value="{Binding ListeCommandes, Converter={StaticResource CommandesToGroupesConverter}}" />
<Setter Property="GroupSizeReductionOrder" Value="{Binding ListeCommandesOrdreRedimensionnement}" />
<Setter Property="ItemContainerStyleSelector">
<Setter.Value>
<ribbonVM:RibbonGroupStyleSelector>
<ribbonVM:RibbonGroupStyleSelector.GenericStyle>
<Style TargetType="{x:Type r:RibbonGroup}" BasedOn="{StaticResource RibbonGroupStyle}" />
</ribbonVM:RibbonGroupStyleSelector.GenericStyle>
</ribbonVM:RibbonGroupStyleSelector>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</r:Ribbon.Style>
And my RibbonGroup's style :
<Style x:Key="RibbonGroupStyle" TargetType="{x:Type r:RibbonGroup}" BasedOn="{StaticResource RibbonControlStyle}">
<Setter Property="Header" Value="{Binding Libellé}" />
<Setter Property="ItemsSource" Value="{Binding Commandes}" />
<Setter Property="CanAddToQuickAccessToolBarDirectly" Value="False" />
<Setter Property="ihm_behaviors:RibbonGroupNameBehavior.IsEnabled" Value="True" />
</Style>
Databinding the GroupSizeReductionOrder property
If you look at the definition of the GroupSizeReductionOrder property, you'll see it's a StringCollection with a TypeConverter StringCollectionConverter.
From what I have seen, this converter only converts from string to StringCollection.
So your property shoud be either a string or a StringCollection.
In Silverlight 4 (using Expression Blend 4), how can I alter the Font size of a TextBox within the style of the Border containing it? I'm converting the style from WPF to Silverlight (fun always). Here is what I have:
<Style x:Key="Title" TargetType="Border">
<Setter Property="TextBlock.VerticalAlignment" Value="Center"/>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<Setter Property="TextBlock.FontSize" Value="48"/>
<Setter Property="TextBlock.Foreground" Value="{StaticResource TextForeground}"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource TitleBackground}"/>
<Setter Property="Padding" Value="25,0"/>
</Style>
It is not working. It gives me the following exception in the designer:
Edits:
Ok, I know this is possible in WPF. Is it simply not possible in Silverlight (without taking on a whole theme construct as Xin suggests?)
Actually you might be able to get what you want from silverlight toolkit themes. You can find it here (Theming -> Theme Browser).
Update:
First you need to create a class that inherits from the Theme (System.Windows.Controls.Theming). I basically copied from the source code and renamed it.
/// <summary>
/// Implicitly applies the border theme to all of its descendent
/// FrameworkElements.
/// </summary>
/// <QualityBand>Preview</QualityBand>
public class BorderTheme : Theme
{
/// <summary>
/// Stores a reference to a Uri referring to the theme resource for the class.
/// </summary>
private static Uri ThemeResourceUri = new Uri("/theming;component/Theme.xaml", UriKind.Relative);
/// <summary>
/// Initializes a new instance of the ExpressionDarkTheme class.
/// </summary>
public BorderTheme()
: base(ThemeResourceUri)
{
var a = ThemeResourceUri;
}
/// <summary>
/// Gets a value indicating whether this theme is the application theme.
/// </summary>
/// <param name="app">Application instance.</param>
/// <returns>True if this theme is the application theme.</returns>
public static bool GetIsApplicationTheme(Application app)
{
return GetApplicationThemeUri(app) == ThemeResourceUri;
}
/// <summary>
/// Sets a value indicating whether this theme is the application theme.
/// </summary>
/// <param name="app">Application instance.</param>
/// <param name="value">True if this theme should be the application theme.</param>
public static void SetIsApplicationTheme(Application app, bool value)
{
SetApplicationThemeUri(app, ThemeResourceUri);
}
}
Then you just need to create a resource dictionary and name it Theme.xaml, and put all your styles inside.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Border">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource TitleBackground}"/>
<Setter Property="Padding" Value="25,0"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="FontSize" Value="48"/>
<Setter Property="Foreground" Value="{StaticResource TextForeground}"/>
</Style>
</ResourceDictionary>
Last, wrap your Border with it!
<local:BorderTheme>
<Border>
<TextBlock Text="TextBlock"/>
</Border>
</local:BorderTheme>
That's it. You should be able to see the styles applied to your Border as well as your TextBlock. :)
I've added PresentationFramework.Aero to my App.xaml merged dictionaries, as in...
<Application
x:Class="TestApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml" />
<ResourceDictionary
Source="pack://application:,,,/WPFToolkit;component/Themes/Aero.NormalColor.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpf;component/ResourceDictionaries/ButtonResourceDictionary.xaml" />
<!-- Note, ButtonResourceDictionary.xaml is defined in an external class library-->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I'm trying to modify the default look of buttons just slightly. I put this style in my ButtonResourceDictionary:
<Style TargetType="Button">
<Setter Property="Padding" Value="3" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
All buttons now have the correct padding and bold text, but they look "Classic", not "Aero". How do I fix this style so my buttons all look Aero but also have these minor changes? I would prefer not to have to set the Style property for every button.
Update
I should have mentioned this in the first place, but if I try to use BasedOn, as shown below, I get a StackOverflowException:
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
<Setter Property="Padding" Value="3" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
This would normally work, but not with the Aero dictionaries merged in. If I comment those dictionaries out, the exception disappears.
Update 2
If I add an x:Key attribute and manually set the style, it works properly (Aero style with padding and bold), but as I said, I'd prefer that the style is automatically applied globally to all buttons.
Update 3
I just discovered a new wrinkle. In my app, ButtonResourceDictionary.xaml is placed in a class library (i.e., in an external project). If I move this file to a local folder, everything works fine. So, the problem seems to be a bad interaction caused by referencing various external resource dictionaries. I'm correcting my App.xaml code snippet (above) to reflect that ButtonResourceDictionary is actually defined externally.
I hope you've found a solution in the meantime. For everyone else, here is one workaround, and here is another. I am not sure whether this will help for your specific case though (especially the fact that you reference an embedded resource dictionary).
UPDATE
Here's a solution I came up with:
<Style TargetType="TextBox" BasedOn="{Common:StaticApplicationResource {x:Type TextBox}}">
<Setter Property="Height" Value="21"/>
</Style>
Where StaticApplicationResource is a custom MarkupExtension I wrote that simply calls TryFindResource:
[MarkupExtensionReturnType(typeof(object))]
public class StaticApplicationResource : MarkupExtension
{
public StaticApplicationResource(object pResourceKey)
{
mResourceKey = pResourceKey;
}
private object _ResourceKey;
[ConstructorArgument("pResourceKey")]
public object mResourceKey
{
get { return _ResourceKey; }
set { _ResourceKey = value; }
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (mResourceKey == null)
return null;
object o = Application.Current.TryFindResource(mResourceKey);
return o;
}
}
This way I don't have to reference my resource dictionaries outside of my App.xaml file , which is the way I like it :). You can also put more complicated logic in there too, allowing you to resolve the BasedOn style any way you like. Here is an excellent article showing you how to load resource dictionaries (and those that the framework resolves automatically) from code.
Based on your updates, you could do this (admittedly it is hideously ugly):
<Style x:Key="_buttonStyleBase"
BasedOn="{StaticResource {x:Type Button}}"
TargetType="{x:Type Button}">
<Setter Property="Padding" Value="3" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style TargetType="{x:Type Button}"
BasedOn="{StaticResource _buttonStyleBase}" />
Use the BasedOn attribute to inherit the properties from the Aero Style. This should solve your problem.
<Style
BasedOn="{StaticResource {x:Type Button}}"
TargetType="{x:Type Button}">
<Setter Property="Padding" Value="3" />
<Setter Property="FontWeight" Value="Bold" />
</Style>