I am trying to style a RadChart. It is a bargraph and I want to change the default colors of the bars. So I used the RadChart.PaletteBrushes and defined SolidBrush colors(Found this method in the following link : http://www.telerik.com/help/wpf/radchart-styling-and-appearance-styling-chart-series.html) as follows:
<telerik:RadChart Background="Transparent" HorizontalContentAlignment="Center" HorizontalAlignment="center">
<telerik:RadChart.PaletteBrushes>
<SolidColorBrush Color="#FF0B3F74"/>
<SolidColorBrush Color="#FF721111"/>
<SolidColorBrush Color="#FFA1720B"/>
</telerik:RadChart.PaletteBrushes>
</telerik:RadChart>
But now, an exception as follows occurs while running the application :
'System.Windows.Media.SolidColorBrush' must have IsFrozen set to false to modify.
This exception occurs randomly. Also, in the stack trace, there is a mention of RadTransition Control too. Why could this error be occuring? How can it be solved?
We also had the same problem, but with a variety of controls. After trading info with Microsoft, they said there was a bug in the Freeze implementation (fix coming in .NET 4.5, perhaps). In the meantime, we now freeze brushes on creation.
Add this namespace to your XAML:
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Then add po:Freeze=true to your brushes:
<SolidColorBrush x:Key="SearchGridHeaderBrush" Color="{StaticResource DefaultHeaderColor}" po:Freeze="true" />
Related
In my current project I have a quite large WPF based application with lots of Static and DynamicResources.
Because of many refactorings and changes in the past there are lots of DynamicResources that can not be found during runtime and therefore no value is applied.
What I like to do is run the application and get an output, exception or whatever when a DynamicResource could not be found.
I have tried to build a DefaultTraceListener and a Converter that checks for unused DynamicResources, but to no avail.
Does anyone have a solution for me on how to achieve that?
Example:
<Grid.Resources>
<Style x:Key="myStyle1" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Blue"></Setter>
</Style>
</Grid.Resources>
<StackPanel>
<TextBlock Style="{DynamicResource myStyle1}">DynamicResource exists</TextBlock>
<TextBlock Style="{DynamicResource myStyle3}">DynamicResource does not exist</TextBlock>
</StackPanel>
How can I be informed during runtime that myStyle3 does not exist?
Thanks in advance !
There are many tools that show you witch binding doesn't work..
WPF Inspector is my favorite tool, take a look. WPF Inspector
Snoop utility is one of those. In short - in the top right corner you'll find DropDown list which allows filter visuals, just select Visuals with binding Error. Source: How to locate the source of a binding error?
In Visual Studio, you can enable all exceptions (with binding errors) in the Debug menu, Exceptions, then check everything.
But I don't know if it's exactly what you want, let other people answer this...
Hopefully this should be an easy one, i have a background of a rectangle i want to display as the phone accent colour or a disabled color based on a boolean in my view model.
I assume that converters are the way to go, but not sure of the syntax to get access to the static resources.
<Rectangle.Fill>
<SolidColorBrush Color="{StaticResource PhoneAccentColor}"/>
</Rectangle.Fill>
Grab the code for a generic BoolToValueConverter from this blog article:-
A Generic Boolean Value Converter
Also include in your code this specialisation for a converter to a Brush:-
public class BoolToBrushConverter : BoolToValueConverter<Brush> { }
Now add the converter to your Xaml like this:-
<Grid.Resources>
<local:BoolToBrushConverter x:Key="DisabledBrushConv"
FalseValue="{StaticResource PhoneAccentBrush}"
TrueValue="{StaticResource PhoneDisabledBrush}" />
</Grid>
Then in rectangle :-
<Rectangle Fill="{Binding Disabled, Converter={StaticResource DisabledBrushConv}}" ... />
This assumes the property in your view model is called Disabled.
You have two options:
Use a converter
Define a property on your viewmodel that returns a Brush based on the boolean value. I would prefer this solution because the performance hit of converters are more noticable on the phone than on the desktop.
I implemented skinning in my application. The application loads its Brushes.xaml resource dictionary which uses colors which reside in a skin-specific resource dictionary. So only one Color.xaml is loaded depending on the chosen skin.
Skin-Specific Color.xaml
<Color x:Key="TextBoxBackgroundColor">#C4AF8D</Color>
<Color x:Key="TextBoxForegroundColor">#6B4E2C</Color>
<Color x:Key="ToolBarButtonForegroundColor">#6B4E2C</Color>
Brushes.xaml:
<SolidColorBrush
x:Key="TextBoxBackground"
Color="{DynamicResource TextBoxBackgroundColor}" />
<SolidColorBrush
x:Key="TextBoxForeground"
Color="{DynamicResource TextBoxForegroundColor}" />
As you can see, multiple colors (TextBoxForegroundColor and ToolBarButtonForegroundColor) are the same. I'd like to circumvent that as it is getting more and more confusing especially since the used colors are not recognizable by their hex value. You could advise now to merge both Colors into one but I have skins where the TextBoxForegroundColor is different from the ToolBarButtonForegroundColor.
What I would like to do is something like this:
<Color x:Key="DarkBrown">#C4AF8D</Color>
<Color x:Key="TextBoxBackgroundColor" Color={StaticResource DarkBrown} />
<Color x:Key="ToolBarButtonForegroundColor" Color={StaticResource DarkBrown} />
Is this at all possible in Xaml? I didn't find a way.
This?
<Color x:Key="DarkBrown">#C4AF8D</Color>
<DynamicResource x:Key="TextBoxBackgroundColor" ResourceKey="DarkBrown"/>
<DynamicResource x:Key="ToolBarButtonForegroundColor" ResourceKey="DarkBrown"/>
For more advanced use cases and multiple levels of aliasing see this answer.
Why don't you just make Brushes.xaml skin-specific? Then you will have this:
<Color x:Key="DarkBrown">#C4AF8D</Color>
<SolidColorBrush x:Key="TextBoxBackgroundBrush" Color="{StaticResource DarkBrown}" />
<SolidColorBrush x:Key="ToolBarButtonForegroundBrush" Color="{StaticResource DarkBrown}" />
Another point in favor of making brushes skin-specific is that there are situations where you would want to make the ToolBarButtonForegroundBrush a solid color brush in one skin and a gradient brush in another skin.
H.B.'s answer is very interesting and I have played around with it quite a bit since I want to do exactly what this question is asking to do.
What I've noticed is that using a DynamicResource doesn't work for WPF 3.5. That is, it throws an exception at run time (the one Amenti talks about). However, if you make colors that are referencing the color you want to share ... a StaticResource, it works on both WPF 3.5 and WPF 4.0.
That is, this xaml works for both WPF 3.5 and WPF 4.0:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ColorsReferencingColors.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640"
Height="480"
>
<Window.Resources>
<Color x:Key="DarkBlue">DarkBlue</Color>
<StaticResource x:Key="EllipseBackgroundColor" ResourceKey="DarkBlue"/>
<SolidColorBrush
x:Key="ellipseFillBrush"
Color="{DynamicResource EllipseBackgroundColor}"
/>
</Window.Resources>
<Grid>
<StackPanel Margin="25">
<Ellipse
Width="200"
Height="200"
Fill="{DynamicResource ellipseFillBrush}"
/>
</StackPanel>
</Grid>
</Window>
Another thing that bears mentioning (again) is that this approach wreaks havoc with the designers out there (i.e the Visual Studio 2008 and 2010 designers, the Blend 3 and 4 designers). I speculate that this is the same reason why Kaxaml 1.7 wasn't liking H.B.'s xaml (if you're following the comment stream on H.B.'s answer).
But while it breaks the designers for a simple test case, it doesn't seem to break the design surface for the large scale application I work on in my day job. Plain weird! In other words, if you care about things still working in the designer, try this method out anyway ... your designer may still work!
That last part is not possible as a Color has no Color property.
A Color does have an R, G, B and A property. So you could create four bytes as resources:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:Byte x:Key="r">#23</sys:Byte>
<sys:Byte x:Key="g">#45</sys:Byte>
<sys:Byte x:Key="b">#67</sys:Byte>
<sys:Byte x:Key="a">#FF</sys:Byte>
<Color x:Key="c1" R="{StaticResource r}"
G="{StaticResource g}"
B="{StaticResource b}"
A="{StaticResource a}"/>
<Color x:Key="c2" R="{StaticResource r}"
G="{StaticResource g}"
B="{StaticResource b}"
A="{StaticResource a}"/>
</ResourceDictionary>
Still not what you might prefer but it should work.
I'm trying to use a StaticResource in a ControlTemplate for a custom object, and whenever that object is rendered, the application crashes. As you can see in the code below, I define both the template and the resource in App.XAML. I've been doing a bit of searching to see if/why this isn't allowed, but have had no luck so far.
<Color x:Key="PersonBackground">#FF003B00</Color>
<ControlTemplate x:Key="PersonTemplate" TargetType="this:Person">
<Border Background="{StaticResource PersonBackground}" BorderBrush="White"
BorderThickness="2" CornerRadius="10" MinHeight="70" MinWidth="120">
...
</ControlTemplate>
If anyone could explain why this isn't allowed or what I'm doing wrong (or, best yet, a better way to do custom theming in Silverlight), I would greatly appreciate it.
Edit: I feel like I should specify that I'm mostly just interested in being able to set the color scheme in one place; the rest of the theme won't need to change as much.
Instead of Color, can you try using a SolidColorBrush
<SolidColorBrush x:Key="PersonBackground" Color="#FF003B00"/>
I'm using the M-V-VM pattern in WPF and I have a background brush I'm going to be using rather often and I'd like to move it out in to a shared ResourceDictionary.
The only problem is the brush uses a color which it gets via Databinding to its hosted context.
Is there anyway I can move the brush out in to a ResourceDictionary and still have it find the value it needs?
The Brush:
<RadialGradientBrush>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5"
CenterY="0.5"
ScaleX="2.3"
ScaleY="2.3" />
<TranslateTransform X="-0.3"
Y="-0.3" />
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="{Binding Path=BackdropColor}"
Offset="1.2" />
<GradientStop Color="#FFFFFFFF"
Offset="-0.1" />
</RadialGradientBrush>
After re-factoring it out to a ResourceDictionary and adding a key, I called it as such:
<StackPanel Grid.Row="0"
Margin="0,0,0,0"
Orientation="Horizontal"
Background="{DynamicResource BackdropRadGradBrush}">
But this resulted in this output in the debugger:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=BackdropColor; DataItem=null; target element is 'GradientStop' (HashCode=16001149); target property is 'Color' (type 'Color')
I don't think that you can keep this Brush in your resource dictionary and use binding to pull in the color. Since the brush is only created once (which is why you want it in the resource dictionary in the first place), at the time of creation WPF doesn't know where it will be used, so it can't pull in the value for the color.
If the color were kept in Setings, for example, that would probably work - but I'm guessing that won't help you, because you probably want the color to change on each control that it is used on (otherwise, you could just hard code the color or it would already be in settings).
Maybe you could create a RadialGradientBrush subclass, and expose the first GradientStop color as a DependencyProperty? You could then create an instance of this subclass wherever you need it, and use binding to pull in the correct color there.
This is a little late, but take a look at using a StaticResource or a DynamicResource instead of a Binding - it will allow you to access another Resource. Not quite Binding, but it's better than nothing.