Using DynamicResource in another resource - c#

I have SolidColorBrush and DrawingImage (vector icon) as XAML resources, both on a global level, in Application.Resources. DrawingImage have GeometryDrawing inside which uses aforesaid brush as DynamicResource.
Looks like this:
<SolidColorBrush x:Key="brushPrimaryColor"/>
<DrawingImage x:Key="iconMain">
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource brushPrimaryColor}"/>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
It is working initially, but changing (swapping for new brush) brushPrimaryColor at a runtime does not reflect on iconMain. DrawingImage is also used as DynamicResource, not frozen and i can change it directly in code.
Basically what i want is to make changeable palette from few brushes for set of vector icons. Is it possible to do with resources, or should i copy resource at a runtime and bind to that copy instead?

Most resources that extend Freezable and are defined in the App.xaml ReeourceDictionary are frozen by default (by the XAML engine). For example, brushes defined in the global ResourceDictionary (App.xaml) are expected to be shared across the application. In other words, the name scope of App.xaml is global and resources with the same resource key cannot appear at a different node in the resource tree (they are unique). It's safe to assume that App.xaml resources are shared. Therefore, to improve performance the XAML engine will freeze every Brush defined in App.xaml, based on the assumption that Brush resources will be treated like static resources.
To change this behavior, you must explicitly instruct the XAML engine to not share this kind of resources. You do this by setting the x:Shared attribute to false. This way the XAML engine will not assume that resources are referenced as static resource and thus will not freeze the Freezable resource.
As mentioned before the default behavior is that the XAML parser will share resources. The x:Shared attribute therefore defaults to true.
To solve your issue, set x:Shared on the resource to false:
App.xaml
<!-- Prevent global Brush from being frozen by the XAMK engine
by setting x:Shared to False -->
<SolidColorBrush x:Key="brushPrimaryColor"
x:Shared="False" />
<DrawingImage x:Key="iconMain">
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource brushPrimaryColor}"/>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>

Related

Change Resource Color from c# code in Windows 8 application

I want to change the color of a SolidColorBrush in a xaml, from c# code, while the app is running.
(This is a Pie chart from WinRT XAML Toolkit, and I want change the color of the slices.)
<charting:Chart.Palette>
<charting:ResourceDictionaryCollection>
<ResourceDictionary>
<SolidColorBrush x:Key="MyBrush" Color="#4586d8"/>
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background" Value="{StaticResource MyBrush}"/>
</Style>
</ResourceDictionary>
</charting:ResourceDictionaryCollection>
</charting:Chart.Palette>
Since there is no DynamicResource in Win8 apps, this is how i tried to set with no success:
Color yellow = Color.FromArgb(0xff, 0xff, 0xb9, 0x01);
Application.Current.Resources["MyBrush"] = new SolidColorBrush(yellow);
How could I set the color of the resource?
I think in WPF DynamicResource would basically create a new instance every time it's requested and would reevaluate on changes in the resource dependency hierarchy. Depending on what you want done - you would approach it differently in your case. You can update the styles/templates to change the base colors, you can change visual states to make these respond to a state change that would change the colors, you can write an attached behavior (using an attached property directly or some open source WinRT behaviors implementation) that you would set on your data points that would update the brushes based on event or bound property, you can traverse the visual tree to update the colors based or you can create two almost identical, overlaid chart controls with different colors and change the colors by changing visibility of the chart controls. Then again maybe you could somehow just bind the brush of a pie chart data point to the underlying data - I haven't checked if that's possible, but if it isn't - you could modify the code of the chart controls to give you that feature (it's the power of open source!)

Image.OpacityMask on WinRT XAML

Regarding this .net XAML UIElement property, Image.OpacityMask: http://msdn.microsoft.com/en-us/library/ms743320.aspx
I am having difficulty getting OpacityMask to work in my C# / XAML project for WinRT.
Sample XAML like this:
<Image ...
<Image.OpacityMask>
<ImageBrush ImageSource="Assets/alpha.png"/>
</Image.OpacityMask>
/>
Doesn't seem to work, "The attachable property OpacityMask property was not found in type Image"
How does one use an alpha mask .png to mask a Image UIElement in WinRT XAML?
There is no OpacityMask property on Image (or UIElement fo that matter) in XAML for Windows Store apps. You only have Opacity property available.
Depending on what you are trying to do, there are alternatives to OpactiyMask that you should check out. check out these alternatives here.

VisualBrush no longer works for Windows 8 Metro Apps?

I'm now developing an app with reflect effect. I tried to assign a VisualBrush to Rectangle.Fill as:
<Rectangle.Fill>
<VisualBrush Opacity="0.75" Stretch="None" Visual="{Binding ElementName=ReflectedVisual}">
</VisualBrush>
</Rectangle.Fill>
And VS reports VisualBrush doesn't exist in my xml namespace. I manually added it to the XAML file using:
xmlns:fx="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
And added the reference DLL as well. However, now VS says that I cannot assign a VisualBrush to a property of class Brush.
This seemed weird to me, as I recalled the same code worked well on Vista. Does anyone know if there's anything I'm missing here?
Thanks.
Metro apps do not have the same set of XAML brushes, resources and elements available as in WPF.
A work-around would have been to use a WriteableBitmap and use the Render method to draw the element to the bitmap. Unfortunately the current version does not support the Render method.

Changing Display color of PNG with transparency in XAML

I have some PNGs with transparency that I use for buttons in my WPF/C# application.
Right now I have two versions of each PNG, one for normal view and one for hover, each a different color. However, I would really like to just have one single PNG and maybe make everything that's not transparent white (each image is all one color, no detail other than shape.
Would it be possible to then alter the color of each using a SolidColorBrush or similar and create the Normal/Hover versions as a static resource in my XAML?
Something like this:
<Image Key="BtnMenu" Source="Images/Menu.png" Fill="ButtonNormalBrush" />
<Image Key="BtnMenuHover" Source="Images/Menu.png" Fill="ButtonHoverBrush" />
Yeah, I totally made up the "Fill" thing...
But the basic idea is that I have a ResourceDictionary that contains the color scheme that is used throughout the entire application, which makes it so that I can change any of the about 6 colors I use in the application in one place and it updates on every control that references that color... but the one place I cannot do it is those PNGs for the buttons. (Ideally in the future I'll make that ResourceDictionary something that can be loaded in at runtime to make the application have alternate "skins"..but right now the PNGs keep me from doing that).
Edit: BTW, if the solution requires a Converter or something written in code, that's totally fine.
Hmm... If you created a Grid, and put the Image inside that Grid, you could set the Background of the Grid to your fill color.
Edit: Here is some code:
<Button>
<Grid Background="SkyBlue">
<Image Source="img.png" Stretch="None" />
</Grid>
</Button>
There is a solution: http://msdn.microsoft.com/ru-ru/library/ms752364.aspx
You can simply create ImageSource with new Format-object from another ImageSource. Format object specifies color mask for an Image.
You could try to apply a ShaderEffect as the Effect on the hover image or create a markup extension which transforms your image. Another possibility would be to encapsulate such logic in a subclass of Image.

How to set a Code-based rectangle's style from a XAML resource file by code

I created a resource file as 'Style' which sets the fillcolor and border of a rectangle.
In 'code' I create a rectangle which is dynamic in size as it's being set by another rectangle size.
What I want is to create the code-based rectangle and have its style set by the resource xaml-file.
How can I do this other then to set it by code.
If possible I don't want to use XamlReader.
You could create a style that would apply to all Rectangles, by specifying only the target type and no x:Key:
<Style TargetType="{x:Type Rectangle}">
...
</Style>

Categories

Resources