Is it possible in XAML to add a reference to resource? For example I have
<Color x:Key="LightRed">#e24c3f</Color>
and I need to have something like
<Color x:Key="ErrorColor">*LightRed*</Color>.
No, a Color resource cannot reference another Color resource if that's what you are asking.
As suggested by #Nawed Nabi Zada, you may define a brush that uses any color resource though:
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource LightRed}"/>
You can easily change the colour of the brush in one place.
Related
I'm designing some themes for my C# / XAML application and would like to define my theme in one XAML file (ResourceDictionary), with variations in colour in several other XAML files (ResourceDictionaries).
So, I'm attempting:
<Style TargetType="ListBox">
<Setter Property="Foreground" Value="{StaticResource ResourceKey=ForegroundBrush}" />
<Setter Property="Background" Value="{StaticResource ResourceKey=BackgroundBrush}" />
</Style>
In a generic theme XAML file which is in a class library and is not referenced from my main app. I then have a second file:
<Color x:Key="BackgroundColour" A="#FF" R="#10" G="#10" B="#40" />
<Color x:Key="BackgroundColour2" A="#FF" R="#10" G="#10" B="#FF" />
<Color x:Key="BorderColour" A="#FF" R="#00" G="#00" B="#FF" />
<Color x:Key="ForegroundColour" A="#FF" R="#FF" G="#FF" B="#FF" />
<Color x:Key="ForegroundColour2" A="#FF" R="#80" G="#80" B="#FF" />
<LinearGradientBrush x:Key="GradientForegroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{StaticResource ForegroundColour}" Offset="0"/>
<GradientStop Color="{StaticResource ForegroundColour2}" Offset="1"/>
</LinearGradientBrush>
I can obviously then have several of these files defining different colours on the same basic theme. I have attempted:
<ResourceDictionary Source="basestyle.xaml" x:Key="basestyle" />
I would then reference bluestyle.xaml, redstyle.xaml etc... from my application. This works well if I copy the entire theme across to each file, but being able to reuse the basic code seems neater.
Is there a way to do this?
If you want to separate the resources like brushes or specific styles from your theme styles and control templates, you can simply create the generic Themes\Generic.xaml resource dictionary with references to recource keys as you did in your example with e.g. ForegroundBrush.
Then you can create a specific style resource dictionary, e.g. redstyle.xaml that contains all the resources with the correspondig keys. Alternatively, you could additionally create another basestyle.xaml resource dicitonary that contains some resources shared by all conrete theme variations that you do not want to store in the theme resource dictionary either.
In order to apply a style, add the necessary resource dictionaries to the App.xaml file as merged dictionaries. Please note, that the order matters. Include resource dictionaries that are needed by other resource dictionaries first. The lookup of StaticResources and DynamicResources will find the resource with a matching key, that was added last here. For more information on that, refer to Lookup behavior for XAML resource references.
<Application x:Class="YourApplication"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Base style that includes all default resources and styles. -->
<ResourceDictionary Source="basestyle.xaml"/>
<!-- Red style that includes just specific resources and style that changed. -->
<ResourceDictionary Source="redstyle.xaml"/>
<!-- Your control theme that references the resources and styles. -->
<ResourceDictionary Source="Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
If you intend to switch the styles at runtime, you will have to replace the corresponding dictionaries in code, e.g.:
In App.xaml.cs by modifying the Resources dictionaries
By using Application.Current.Resources.
If you do not replace all dictionaries, including your generic control themes dictionary, you will have to use the DynamicResource markup extension instead of StaticResource, because the latter one does not pick up changes to references resources at runtime.
The StaticResource Markup Extension processes a key by looking up the value for that key in all available resource dictionaries. Processing happens during load, which is when the loading process needs to assign the property value. The DynamicResource Markup Extension instead processes a key by creating an expression, and that expression remains unevaluated until the app runs, at which time the expression is evaluated and provides a value.
Yes you can create different Resource.xaml files in same project, you just need to load that files in App.cs code as,
if(_theme=="theme1")//you can use switch statement if themes are more
{
ResourceDictionary myResourceDictionary1 = new ResourceDictionary();
myResourceDictionary1.Source = new Uri("theme1.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary1);
}
else
{
ResourceDictionary myResourceDictionary2 = new ResourceDictionary();
myResourceDictionary2.Source = new Uri("theme2.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary2);
}
EDIT: Looks like this was related to the way I declared the color - using hex value seems to bring it through fine.
EDIT: This about referencing from the App.xaml file. The color itself works fine if declared as a local resource.
I've created a colour:
<SolidColorBrush x:Key="TestBlue">
<SolidColorBrush.Color>
<Color R="0" G="86" B="45"/>
</SolidColorBrush.Color>
</SolidColorBrush>
and placed it in a ResourceDictionary. I've then referenced it in a MergedDictionary:
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Colours.xaml"/>
<ResourceDictionary Source="View\Item\ItemResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
When I apply it to the background of a Button as a StaticResource it doesn't apply:
Background="{StaticResource TestBlue}"
When I Snoop the control it declares the Background as some other value:
It also doesn't work if I make it an entry in the itself (like the ViewModelLocator). It does work if I place it in the Window.Resources. Any ideas what's going on here?
You need to provide value for Alpha (transparency) channel, because Color is structure and it's default value for that value is zero (transparent).
<Color A="255" R="0" G="86" B="45"/>
To use it as a StaticResource, you must include your ResourceDictionnary where you want to use your Resource. Otherwise, you'll have to use it as a DynamicResource.
So if your button is in its own xaml file, you'll have to include your ResourceDictionnary in the button's xaml file, as you did in App.xaml.
In my XAML I have this:
<Color x:Key="VeryLightGrey">#fff0f0f0</Color>
<Color x:Key="TabBackgroundColor">#fff0f0f0</Color>
I would love to have something like this:
<Color x:Key="TabBackgroundColor" Color="{StaticResource VeryLightGrey}"/>
I have tried various methods including this:
<StaticResource x:Key="TabBackgroundColor" ResourceKey="VeryLightGrey"/>
But my code become riddled with warning about:
"An object of type System.Wndows.StaticResourceExtention cannot be applied to a property that expects the type System.Windows.Media.Color"
Other posts say to ignore this warning, but it actually causes problems, so i cant.
Is there a better solution out there ?
You could declare the color once and define multiple brushes that use the same color.
Use the Brushes for your UI Elements.
I am creating a custom control with two text colors, ColorA and ColorB. ColorA is wired to the Foreground property of the control, and ColorB is wired to a custom dependency property called ForegroundAlt. Both properties are Brush objects. The control's XAML gets the property values using this markup:
<SolidColorBrush x:Key="BrushA" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
<SolidColorBrush x:Key="BrushB" Color="{Binding Path=ForegroundAlt, RelativeSource={RelativeSource TemplatedParent}}" />
I need to animate sme text between the two colors in the control template, and that's where I am running into problems.
Normally, I would simply create a data binding to each Brush.Color property, like this:
To="{Binding Source={StaticResource BrushB}, Path=Color}"
But that won't work here. It turns out that you can't use bindings on an animation inside a control template.
As a workaround, I would like to create a pair of Color resources to go along with the Brush resources:
<Color x:Key="ColorA" ??? />
<Color x:Key="ColorB" ??? />
Each Color resource should have the color of its corresponding brush. I could then reference the colors as static resources, and avoid having to data bind from within the animation.
So, here are my questions:
-- How would I declare the Color resources?
-- Is there a simpler way to get the job done?
Thanks for your help.
If I've understood this correctly, what you are trying will not work. Even if you define the Colors as resources, you will still have to bind them to the brush resources and you are back to square one!
One solution is to do it in code behind rather than in the template. Since its a custom control you are building its should be pretty straightforward to add it in th code behind without screwing up the design.
I need to change the highlight color of a ComboBox's selected item in the popup list. I've found several tutorials explaining how to do this, but all of them either use Blend, which I do not have and cannot obtain, or involve changing the system default colors--which seems like a hack to me.
Can someone point me to the template I need to override, or tell me the property I need to set?
Override the SystemColors.HighlightBrushKey (and SystemColors.HighlightTextBrushKey if you want):
<ComboBox>
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}">Red</SolidColorBrush>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Blue</SolidColorBrush>
</ComboBox.Resources>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
</ComboBox>
I have created a template for Combobox here :
http://wpfstyles.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31388#DownloadId=78720
Thanks,
Vikas