Fixed gradient with a moving rectangle? - wpf

I have a WPF 'monitor widget' that displays CPU, RAM and disk performance as small percentage bars. I use the following gradient as a resource to divide the bars into 4 sections (ie. 0% - 25%, 25% - 50%, etc.)
<LinearGradientBrush x:Key="Quarters" StartPoint="0,0" EndPoint="0,15" MappingMode="Absolute">
<GradientStop Color="LightGreen" Offset="0.0" />
<GradientStop Color="LightGreen" Offset="0.24" />
<GradientStop Color="Yellow" Offset="0.25" />
<GradientStop Color="Yellow" Offset="0.49" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Orange" Offset="0.74" />
<GradientStop Color="Red" Offset="0.75" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush>
Originally, the bars' 0% position was at the top (bar.Height = 0) and 100% was at the bottom (bar.Height = 15). The bar size would change by simply adjusting its Height property. Everything worked fine, but I would prefer the bars' 0% position to be at the bottom instead, ie. the bars will 'grow' upward.
Making the bars grow upward was no problem, but the problem I do have is that the gradient now moves with the rectangle, so that the top of the rectangle is always green, no matter how small it is. I understand that this is because I am now using Canvas.SetTop to move the top of the rectangles (bars) as well as change their height. How can I force the gradient to an absolute position, regardless of the position of the rectangle?
(background opacity)
Sorry, I know the image is small, but you should just be able to make out that the middle bar starts from the top (green) and grows downward, ending in orange (50% -75% value). The left bar starts at the bottom (this is what I want), but the gradient in this bar moves with the height... this is the problem. Note that I'll reverse the gradient when I can fix this problem, so that red will represent the top 25%. In this example, the bottom quarter should be red, the next quarter orange and the remainder yellow.
I can't believe that there is no simple solution for this... come on brain-boxes. :) How about moving the absolute position of the gradient with the rectangle... is this possible???
(Relating post: Determining a computer's maximum hard drive data transfer rate programmatically with C#)

Update
Clip the rectangle with values set at runtime.
<Window.Resources>
<LinearGradientBrush x:Key="Quarters" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="LightGreen" Offset="0.0" />
<GradientStop Color="LightGreen" Offset="0.24" />
<GradientStop Color="Yellow" Offset="0.25" />
<GradientStop Color="Yellow" Offset="0.49" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Orange" Offset="0.74" />
<GradientStop Color="Red" Offset="0.75" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush>
</Window.Resources>
<Canvas Height="100">
<Rectangle Fill="{StaticResource Quarters}" Width="30" Height="100" Canvas.Bottom="0" Canvas.Left="0">
<Rectangle.Clip>
<RectangleGeometry x:Name="ClipRect" Rect="0, 100, 30, 100" />
</Rectangle.Clip>
</Rectangle>
</Canvas>
Code:
ClipRect.Rect = new Rect(0, 20, 30, 100); //80%
ClipRect.Rect = new Rect(0, 70, 30, 100); //30%
Original Solution
Use 2 rectangles for each bar.
One rectangle with 100% height and the colored gradient. Then overlay a black rectangle over the first rectangle. Adjust the black rectangles height(as you were before) to expose the gradient below.
eg If the value is 25% set the overlay height to 75%

I solved a similar issue using clipping. Create rectangles for 100% and fill with the brush. Then use clipping to only show part of the rectangle, see sample code below which shows two rectangles:
<Window x:Class="GradientTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Window.Resources>
<LinearGradientBrush x:Key="Quarters" StartPoint="0,1" EndPoint="0,0">
<GradientStop Color="LightGreen" Offset="0.0" />
<GradientStop Color="Yellow" Offset="0.25" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="0.75" />
</LinearGradientBrush>
</Window.Resources>
<Canvas Height="100">
<!--21%-->
<Rectangle Fill="{StaticResource Quarters}" Width="30" Height="100" Canvas.Bottom="0" Canvas.Left="0">
<Rectangle.Clip>
<RectangleGeometry Rect="0, 79, 30, 100" />
</Rectangle.Clip>
</Rectangle>
<!--68%-->
<Rectangle Fill="{StaticResource Quarters}" Width="30" Height="100" Canvas.Bottom="0" Canvas.Left="40">
<Rectangle.Clip>
<RectangleGeometry Rect="0, 32, 30, 100" />
</Rectangle.Clip>
</Rectangle>
</Canvas>
</Window>

Yes, the 0,0 point of gradient fill's StartPoint/EndPoint always seems to be the top left of the object.
So one way around that is to rotate the object 180 degrees using a RenderTransform.
Then you can just set the height of the rectangle, but the gradient fill will stay anchored to the bottom.

Related

Linear Gradient from bottom to top

I need an Ellipse with a linear gradient from bottom(pink) to top(red).
<Ellipse Width="200" Height="200">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0" >
<GradientStop Color="Pink" Offset="0" />
<GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
The above code shows a gradient from left bottom to top right.
I need the gradient to move from left middle to top middle.
I tried changing the starting and end point with no success. Is there another property that can be used?
It has to be a linear gradient on a ellipse. I cannot use a radial gradient here.
gradient from Bottom to Top (vertical)
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
gradient from left middle to top middle
<LinearGradientBrush StartPoint="0,0.5" EndPoint="0.5,0">
Visual representation of how it works

Is it possible to apply Gradient to a Background Image in Silverlight?

I want to apply some gradient to my image how can I achieve that?
Thanx
You could host your image within a Border, applying the gradient to the border background:
<Border>
<Border.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Blue" Offset="1" />
</LinearGradientBrush>
</StackPanel.Background>
<Image Source=..your image source .." />
</Border>
This assumes that your image has some opaque regions which will show the gradient beneath it.
In the gradient you can use one or more colours. Any it is very easy to set the gradient using either VS2010 or expression blend. The following is the sample code of a two-colour gradient with blue and white.
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<LinearGradientBrush.RelativeTransform> <CompositeTransform CenterY="0.5" CenterX="0.5" Rotation="-90"/>
</LinearGradientBrush.RelativeTransform>
<GradientStop Color="#FFB6D3F9"/>
<GradientStop Color="#FFFDFDFD" Offset="1"/>
</LinearGradientBrush>

Cursor on Path doesn't appear in SilverLight

I am trying to draw a circle with a glass effect using Alpha. I am successful in creating that by using the below XAML. The cursor changes to Hand for the Ellipses, but it doesn't affect Path. Basically, I want to show "hand" cursor wherever the mouse appears over the circle. I hope this is not a known issue and I am missing something small. Any help is really appreciated.
<Ellipse Cursor="Hand"
Width="200"
Height="200"
Fill="#C42222" Canvas.Left="0" Canvas.Top="0" />
<Ellipse Cursor="Hand" Width="200" Height="200" Canvas.Left="0" Canvas.Top="0">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.3,0.7">
<GradientStop
Offset="0"
Color="#00000000" />
<GradientStop
Offset="1"
Color="#66000000" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path Cursor="Hand" Stretch="Fill" Height="114.598" Width="198.696" Data="M98.388435,-1.3301961 C98.388435,-1.3301961 117.1151,-3.094949 141.69321,8.1370029 C156.42262,14.868201 167.67375,23.694145 175.66234,33.657074 C183.67349,43.648144 181.90166,37.8708 191.90166,58.8708 C201.90166,79.870796 199.16658,89.212738 199.13568,92.90377 C198.77556,135.92146 175.45959,97.59124 156.75465,81.024025 C140.98892,67.060104 117.41241,64.357407 114.41241,64.357407 C111.4124,64.357407 83.061241,60.114159 63.061195,71.114143 C43.061146,82.114136 39.637829,86.429352 22.999804,100.99996 C6.5005584,115.44904 2.9997537,112.99996 2.9997537,112.99996 C2.9997537,112.99996 -1.1832786,97.194221 1.9997513,81.999893 C7.2054667,57.150185 13.999762,47.999939 17.999771,42.999943 C21.999781,37.99995 29.935833,23.400871 54.053131,10.21261 C78.91642,-3.3835876 98.388435,-1.3301961 98.388435,-1.3301961 z">
<Path.Fill>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#55FFFFFF" Offset="0"/>
<GradientStop Color="#11FFFFFF" Offset="0.5"/>
<GradientStop Color="#00FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
I want to show "hand" cursor wherever the mouse appears over the circle.
The hand cursor appears in my testing of your Path when the mouse is over the path. However perhaps the clue might be in your description above. The Path doesn't describe a circle more like a crescent. Add Stroke="Black" StrokeThickness="1" to the path so that you can see its outline and test that the cursor does actually work.
The other possiblity is in your actual Xaml that there is something else that has a hight z-index or appears later in the Xaml document order that overlays the Path.

Is it possible to seletively color a label in Silverlight?

For instance, if I have a label:
Blah blah bladity blah
I want the first 10% of this label, such that the font color should be red, and the rest should be green.
This perhaps means it would color the Bl and PART of the a. Basically pixel-wise font coloring instead of character-wise. Is this possible and how would is be accomplished?
Yeah, it would be like this:
<Canvas>
<dataInput:Label Background="White" >
<dataInput:Label.Foreground>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Red" Offset="0.1"/>
<GradientStop Color="Green" Offset="0.1"/>
</LinearGradientBrush>
</dataInput:Label.Foreground>
Blah blah bladity blah
</dataInput:Label>
</Canvas>
In order to not have the gradient effect, you need to set both Offset to the same value.
Note: In this font size (standard, nothing changed) the "B" and "l" are red and only a small sliver of "a" is. But the "0.1" in Offset means 10%, so you can either decrease font size or change the Offset value.
Yes - you should use a Gradient brush with the Foreground color of the Text.
<TextBlock Text="Blah blah bladity blah">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Red" Offset="0.1"/>
<GradientStop Color="Green" Offset="0.1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>

SVG -> WPF linear gradient

Does anyone know if there is an equilant attribute of SVG's "gradientUnits=userSpaceOnUse" in WPF for a LinearGradientBrush? I can't seem to find this.
If not, does anyone know about how to calculate it in (C# or VB.NET)? For example if I have a StartPoint of 0,0 and EndPoint of 1,1 on a Rectangle that is 100x100, the angle is 45 degrees. However, when I change either the width or height of the Rectangle, for example Width=150, the axis is no longer at 45 degrees. How could I calculate to keep the angle at 45 degrees in a rectangle that is not a square so that it runs from bottom left to top right corner for a middle gradientstop.
Set the brush MappingMode = BrushMappingMode.Absolute
This works like a charm now in the new Silverlight 4 - setting the angle to 45 degrees in RotateTransform does so for the bounding box instead of the shape. Like this:
<Rectangle Width="70" Height="50">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF70202" Offset="0"/>
<GradientStop Color="#FFF7F206" Offset="1"/>
<GradientStop Color="Black" Offset="0.49"/>
<GradientStop Color="Black" Offset="0.51"/>
<GradientStop Color="White" Offset="0.5"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="45"></RotateTransform>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Rectangle.Fill>

Resources