开发者

Fixed gradient with a moving rectangle?

I have a WPF 'monitor widget' that displays CPU, RAM and disk perform开发者_如何学Pythonance 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?

Fixed gradient with a moving rectangle?

Fixed gradient with a moving 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜