Inherit properties from one RadialGradientBrush to another - wpf

Issue
I am attempting to write a style/theme for an application
This is based of a mergedResourceDisctionary
My intention is to inherit dynamic resources from an existing Base Dynamic resource of the same type, in this case
STAC_RGrad_Status_Base
In the example below I have 2 other RadialGradientBrushes all sharing exactly the same properties except the GradientStops
I have already gone some way to inheriting, (See the STAC_RGrad_Status_Green) however is there a simpler way than this where I can replace all 4 Binding statements into a "One Liner" statement which is interpreted as
Properties="{Binding Propterties , Source={DynamicResource STAC_RGrad_Status_Base}} except GradientStops"
Which will allow future proofing should I need to add an additional property to that tree of resources defined in
So instead of creating a binding for each property as I have done in the example
It is replaced by a "one liner"
Existing Code
<RadialGradientBrush x:Key="STAC_RGrad_Status_Base"
GradientOrigin="0.5,0.5"
Center="0.5,0.5"
RadiusX="0.5"
RadiusY="0.5"
GradientStops="{DynamicResource STAC_Grad_Status_Disabled}"
/>
<RadialGradientBrush x:Key="STAC_RGrad_Status_Red"
GradientOrigin="0.5,0.5"
Center="0.5,0.5"
RadiusX="0.5"
RadiusY="0.5"
GradientStops="{DynamicResource STAC_Grad_Status_Red}"
/>
<RadialGradientBrush x:Key="STAC_RGrad_Status_Green"
GradientOrigin="{Binding GradientOrigin, Source={DynamicResource STAC_RGrad_Status_Base}}"
Center="{Binding Center, Source={DynamicResource STAC_RGrad_Status_Base}}"
RadiusX="{Binding RadiusX, Source={DynamicResource STAC_RGrad_Status_Base}}"
RadiusY="{Binding RadiusY, Source={DynamicResource STAC_RGrad_Status_Base}}"
GradientStops="{DynamicResource STAC_Grad_Status_Green}"
/>

Related

Visually split Path into two side-by-side colors in WPF

If I have a rather meandering Path in my WPF app, is there a way I can make it appear as two differently-colored Paths of identical widths side-by-side? I'd rather not try to hand-code the whole thing again with slightly different values. I thought of using a Brush, but the list of Brushes doesn't appear to have one such.
Edit: I want a Path divided sharply by color, even if it curves, like this:
Made a little search, and found that also :
Two-color Path object
Timwi answer :
<StackPanel Orientation="Horizontal">
<StackPanel.LayoutTransform>
<ScaleTransform CenterX="0" CenterY="0" ScaleX="15" ScaleY="15" />
</StackPanel.LayoutTransform>
<Grid Margin="-5,0,0,0">
<Path Fill="Blue" Stroke="Transparent">
<Path.Data>
<PathGeometry>M10,10 C20,10 10,20 20,20 L20,19 C11,19 21,9 10,9</PathGeometry>
<!-- |← original path →| |← generated part →| -->
</Path.Data>
</Path>
<Path Fill="Red" Stroke="Transparent">
<Path.Data>
<PathGeometry>M10,10 C20,10 10,20 20,20 L20,21 C9,21 19,11 10,11</PathGeometry>
<!-- |← original path →| |← generated part →| -->
</Path.Data>
</Path>
</Grid>
</StackPanel>
So "playing" with margin may be much easier that the other options I told you about for what you need.
DropShadowEffect solved my issue.

Path.Data styling works only on first instance of styled object

A have a ListBox of items, every ListBoxItem contains an icon in the form of a Path object, like so:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid ...>
...
<Path Margin="4" Style="{StaticResource ErrorIconPath}"
Stretch="Uniform" Width="26" Height="26"
RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"
UseLayoutRounding="False"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
The Path's style is contained in Appl.xaml (Application.Resources section) and is the following:
<Style x:Key="ErrorIconPath" TargetType="Path">
<Setter Property="Data" Value="F1M874.094,289.369L854.3,254.63C854.028,254.151 853.515,253.856 852.958,253.856 852.403,253.856 851.89,254.151 851.617,254.63L831.824,289.369C831.555,289.84 831.559,290.416 831.835,290.883 832.111,291.348 832.618,291.634 833.165,291.634L872.752,291.634C873.299,291.634 873.805,291.348 874.081,290.883 874.357,290.416 874.361,289.84 874.094,289.369 M855.653,287.189L850.264,287.189 850.264,282.745 855.653,282.745 855.653,287.189z M855.653,279.41L850.264,279.41 850.264,266.077 855.653,266.077 855.653,279.41z" />
</Style>
The trouble is that only the first item in the ListBox binds the Data property as expected, the other ones don't bind it at all (hence they appear as blank space, but match the size of the Path). Also when I use the style anywhere else (i.e. outside the ListBox), only the first instance that occurs will bind.
The weird thing is that if I define for example the Fill property in the Style instead of inline, it works just fine and doesn't exibit the same problems as the Path property.
My guess is that is has something to do with Data not being a primitive type, but I haven't found any fixes.
EDIT: Interestingly, when I bind the Data property directly to System.String resource, it works. I would still like to be able to define this property via a Style though.
EDIT 2: I've just came across the same issue in WPF, when setting Path to a Content of a Button via a Style that is used across more buttons. The path shows up in just one buttons, the others are blank.
Path.Fill is a DependencyProperty, while Path.Data isn't. Instead do:
<DataTemplate>
<Grid ...>
...
<ContentPresenter Content="{StaticResource MyPath}"/>
</Grid>
</DataTemplate>
ContentPresenter.Content is a DependencyProperty so this should work:
<Path x:Key="MyPath" Margin="4" Style="{StaticResource ErrorIconPath}"
Stretch="Uniform" Width="26" Height="26" VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"
UseLayoutRounding="False" HorizontalAlignment="Center"
Data="F1M874.094,289.369L854.3,254.63C854.028,254.151 853.515,253.856 852.958,253.856 852.403,253.856 851.89,254.151 851.617,254.63L831.824,289.369C831.555,289.84 831.559,290.416 831.835,290.883 832.111,291.348 832.618,291.634 833.165,291.634L872.752,291.634C873.299,291.634 873.805,291.348 874.081,290.883 874.357,290.416 874.361,289.84 874.094,289.369 M855.653,287.189L850.264,287.189 850.264,282.745 855.653,282.745 855.653,287.189z M855.653,279.41L850.264,279.41 850.264,266.077 855.653,266.077 855.653,279.41z"/>
I am guessing that Geometry cannot be shared. Have you tried setting the x:Shared= "false" to:
<Style x:Key="ErrorIconPath" TargetType="Path">
I've experienced the same behavior in Silverlight and asked a similar question here on StackOverflow.com
( https://stackoverflow.com/q/13426198/1796930), but as I'm writing this, it's been 1 month and I've yet to get even a single answer.
However, as you mentioned in your first edit, I too was able to perform a workaround by creating a resource with my geometry data as a string and then binding the Data property of the Path objects to the string resource resource.
I also had to create two instances of the Path objects that were identical other than each one using a different resource (i.e. two different icons) and then binding the visibility of each to a property in my ViewModel to display the appropriate one.
I am very sure that you did not forgot the stroke here in Path style
<Setter Property="Stroke" Value="Red"/>
I have tested you code on my machine , it worked fine if above line added in style
My first tought was your Path would be broken or not valid. But then I saw you are using the Syncfusion Metro Studio. I tried it with exactly the same code you have and it worked very well. In a Data Template of 5 Items or as a single Path Item.
Have you tried to set the Fill statically to Red or something?
Also maybe try this for the Style definition
<Style x:Key="ErrorIconPath" TargetType="{x:Type Path}">
Third suggestion would be to move the style definition from the App to your Page or even to your Control itself.
To be sure there will be no default styles applied, try
OverridesDefaultStyle="True"
Hope this helps :)

Silverlight - Reading path data at runtime

I have a work area (grid) where I add and remove objects at runtime, mostly canvases or stackpanels containing different paths.
When I have dragged 'n' dropped all objects I want to my 'drawing', I want to save the data to the database.
I use XamlWriter.Save() to get the string data and it works "fine", but all Path Data is empty:
XAML for Path Data is not available due to Silverlight runtime limitations
<Path StrokeThickness="0.98">
<Path.Data>
<PathGeometry>
<!-- XAML for Path Data is not available due to Silverlight runtime limitations -->
</PathGeometry>
</Path.Data>
<Path.Stroke>
<SolidColorBrush Color="#FF000000">
<SolidColorBrush.Transform>
<MatrixTransform>
<MatrixTransform.Matrix>
<Matrix />
</MatrixTransform.Matrix>
</MatrixTransform>
</SolidColorBrush.Transform>
<SolidColorBrush.RelativeTransform>
<MatrixTransform>
<MatrixTransform.Matrix>
<Matrix />
</MatrixTransform.Matrix>
</MatrixTransform>
</SolidColorBrush.RelativeTransform>
</SolidColorBrush>
</Path.Stroke>
</Path>
Is there any way around this?
I really need to get the path data to be able to save and then later open and continue working on my 'drawing'.
Help and/or other ideas are very welcome..!
Thanks in advance!
//Anna
If RobSiklos' comment doesn't help, you might have to either serialize that data in another way, or manually post process the XML and add the path data yourself.

Enable data binding in shared WPF resources inside a ResourceDictionary

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.

Reuse of StaticResource in Silverlight 2.0

I am currently testing with Silverlight 2.0 Beta 2, and my goal is to define a resource element once and then reuse it many times in my rendering. This simple example defines a rectangle (myRect) as a resource and then I attempt to reuse it twice -- which fails with the error:
Attribute {StaticResource myRect} value is out of range. [Line: 9 Position: 83]
BTW, this sample works fine in WPF.
<UserControl x:Class="ReuseResourceTest.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="200" Height="200">
<Canvas x:Name="LayoutRoot" Background="Yellow">
<Canvas.Resources>
<RectangleGeometry x:Key="myRect" Rect="25,50,25,50" />
</Canvas.Resources>
<Path Stroke="Black" StrokeThickness="10" Data="{StaticResource myRect}" />
<Path Stroke="White" StrokeThickness="4" Data="{StaticResource myRect}" />
</Canvas>
</UserControl>
Any thoughts on what's up here.
Thanks,
-- Ed
I have also encountered the same problem when trying to reuse components defined as static resources. The workaround I have found is not declaring the controls as resources, but defining styles setting all the properties you need, and instantiating a new control with that style every time you need.
EDIT: The out of range exception you are getting happens when you assign a control to a container that already is inside another container. It also happens in many other scenarios (such as applying a style to an object that already has one), but I believe this is your case.

Resources