Thursday, April 26, 2012

Chrome LinearGradientBrush

Wanted to create a way to show a chrome effect, without having several borders or paths layered on top of each other. My coworker (hey there Matt  ( ^_^ )/" ) suggested using brushes only to keep the number of UserControls down to a minimum.

It made sense, and I had to go back to my Adobe Illustrator days (since I am working in Blend right now creating XAML with the Properties panel) and remember that linear gradient fills can be created to look like chrome, using several gradients stops (for XAML it is called a GradientStop for each color and where it falls within the actual brush).

By working with the brushes, and using the gradient tool arrow - I was able to come up with a nice chrome style brush. I'll have to practice to get the chrome to look a bit differently, but this is perfect for what I need it for now.

First: I created a new UserControl to create the brush so I wouldn't accidentally change any of the elements in one of my current controls (which I have done several times before). I just called it LinearBrushCreator, nothing fancy but I know what it is for.

I filled the rectangle with a very basic black and white LinearGradientBrush, which is the default in Blend when you choose to fill the element with a gradient. The image below shows where the brush fill options are in the Properties panel. Select the item, and it will show the different properties that can have a brush applied to it. Since this is a rectangle it has a Fill property (element), if it were a border it would have the Background property for the fill of the shape.



Afterwards, I went to the toolbar and chose the Gradient Tool. When the rectangle is selected and you have the Gradient Tool (The white arrow that is second from the top, or right below the solid black arrow) chosen, there is an arrow that is displayed on the rectangle. This arrow shows the direction of the gradient, and there are points (the little circles) and these represent what color is at that specific GradientStop in the LinearGradientBrush.


Below is the Rectangle with the arrow showing the brushes direction and colors.


The easiest way I found to add and manipulate the colors on the brush is to use the arrow and not the slider on the Properties panel. You can zoom in and out on the arrow's point, instead of trying to move tiny boxes that represent the colors. 

The easiest way to add a GradientStop is to have the Selection Tool (Solid Arrow at the very top of the toolbar) chosen, then click on the arrow. This creates a new point (circle) that you can change the color on by using the Color Selection box in the Properties panel.

After several changes, and adding several points to the arrow, I was able to create a brush fill I was happy with and is consistent with the application's overall theme.

This image shows how many different points I used to create this fill effect.


Below is the finished XAML for this Chrome Brush design.

<LinearGradientBrush x:Key="MyChrome" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FF181818" Offset="0.495"/>
        <GradientStop Color="#FFCACACA" Offset="0.46"/>
        <GradientStop Color="#FFF3F3F3" Offset="0.997"/>
        <GradientStop Color="#FFC8C8C8" Offset="0.788"/>
        <GradientStop Color="White" Offset="0.006"/>
        <GradientStop Color="White" Offset="0.966"/>
        <GradientStop Color="#FF242525" Offset="0.531"/>
        <GradientStop Color="#FF1D1D1D"/>
        <GradientStop Color="White" Offset="0.215"/>
        <GradientStop Color="#FF060606" Offset="0.463"/>
        <GradientStop Color="#FFF1F1F1" Offset="0.006"/>
        <GradientStop Color="#FFFBFBFB" Offset="0.401"/>
        <GradientStop Color="#FF96999B" Offset="0.458"/>
        <GradientStop Color="#FFCCCCCC" Offset="0.434"/>
        <GradientStop Color="#FFD0D0D0" Offset="0.002"/>
    </LinearGradientBrush>


Now, going to try this again (MUCH later though) for a few different patterns that would work better on different controls.

Wednesday, April 25, 2012

Simplified Digital Clock for Silverlight

Another personal note to help me remember how to create a very simple digital clock in Silverlight. Posted if other people are working on a simple clock and don't want to write a lot of code.

Got most of the code from this CodeProject Post.

This is creating a very simple clock display using TextBlocks.

There are four TextBlocks - each are named
1. ClockDay
2. ClockMonth
3.ClockYear
4. ClockTime

In order for the required commands to work, you need the following statements at the very top of the C# codebehind:

using System.Windows.Input;
using System.Threading;
using System.Windows.Media;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

Once those are called, then just setting up the actual codebehind

namespace MyClockApp
{
   public partial class MyDigitalClockDisplay : UserControl
   {
      public MyDigitalClockDisplay()
      {
         InitializeComponent();

         this.LayoutRoot.DataContext = this; // I had other items with bindings on this control

        StartTimer()
      }
   
   private void StartTimer()
   {
      DispatcherTimer myDispatcherTimer = new DispatcherTimer()
      myDispatcherTimer.Interval = new TimerSpan(0,0,1);
      myDispatcherTimer.Tick += new EventHandler(Each_Tick);
      myDispatcherTimer.Start();
    }

   private void Each_Tick(object sender, EventArgs e)
   {

     // A listing of the different string formats for the DateTime are defined on this Microsoft Page.
      ClockDay.Text = DateTime.Now.ToString("dd");
      ClockMonth.Text = DateTime.Now.ToString("MMMM");
     ClockYear.Text = DateTime.Now.ToString("yyyy");
      ClockTime.Text = DateTime.Now.ToString("hh:mm:ss");
}
}
}


Below is an image showing the layout I used and which TextBlock was used for each of the values.



Tuesday, April 24, 2012

"Dynamic" LinearGradientBrush using a public class

(Still working on this - more info later. Below is the code to create the effect)

1. Create a new class object in Blend (or Visual Studio). (Such as ElementItems.cs)
2. In the class, create a public class (such as public class LinearBrushItems... full example below)

namespace ThisApplication
{
   public class ElementItems
    {
       public ElementItems()
        {
         }

       public class LinearBrushItems
      {
           // the line below extracts the EndPoint for the brush. This is why it is defined as a Point
            public Point EndPoint {get; set;}
           // the line below extracts the StartPoint for the brush. This is why it is defined as a Point
           public Point StartPoint {get; set;}
           // sets the GradientStopCollection for the brush
           // the GradientStopCollection defines the GradientStops for the brush, and the colors
           public GradientStopCollection GradientStopCollection {get; set;}
      }
}


The GradientStopCollection is defined in a Resource Dictionary. It is implied in a LinearGradientBrush definition - if the entire framework of the LinearGradientBrush was displayed it would be:

<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
   <GradientStopCollection >
        <GradientStop Color="Blue" Offset="0.296"/>
        <GradientStop Color="Yellow" Offset="0.985"/>
        <GradientStop Color="Green" Offset="0.041"/>
        <GradientStop Color="Red" Offset="0.696"/>
        <GradientStop Color="White" Offset="0.307"/>
        <GradientStop Color="Black" Offset="0.744"/>
    </GradientStopCollection>
</LinearGradientBrush>

Giving the GradientStopCollection a key, and defining in a Resource Dictionary, can be reused without creating a new brush. 

<GradientStopCollection x:Key="RainbowGradientOne">
        <GradientStop Color="Blue" Offset="0.296"/>
        <GradientStop Color="Yellow" Offset="0.985"/>
        <GradientStop Color="Green" Offset="0.041"/>
        <GradientStop Color="Red" Offset="0.696"/>
        <GradientStop Color="White" Offset="0.307"/>
        <GradientStop Color="Black" Offset="0.744"/>
    </GradientStopCollection>



:NOTE:
If there are any LinearGradientBrushes that are an exact duplicate of the GradientStops defined in the GradientStopCollection you will see the error "Value does not fall within the expected range". For example: if the LinearGradientBrush and the GradientStopCollection in this example were defined in the same application (even if in different Resource Dictionaries) - the application will throw this error.

When I got that error, I looked all over and read several possible fixes. When Blend gave me that error - after hitting ok when it asked to see the results panel, that is the error it gave.
It did give another error before I hit the ok on the dialog window. By increasing the results window before building, I was able to see the initial error - which gave the explanation that there was a duplicate definition.

To use the class in a UserControl (haven't tried in a page yet)

<UserControl
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:local = "clr-namespace:This Application"
 x:Class="ThisApplication.GradientTest"/>

<UserControl.Resources>
<!-- The local definition for the LinearGradientBrush Elements HAS to have a key associated with it -->
<local:LinearBrushItems x:Key="BasicRainbowGradient"
                                          EndPoint="0,0"
                                          StartPoint="1,1"
                                          GradientStopCollection="{StaticResource RainbowGradientOne}" />
</UserControl.Resources>

<Border x:Name="ThisBorder">
   <Border.Background>
<LinearGradientBrush
               EndPoint="{Binding Source={StaticResource BasicRainbowGradient}, Path=EndPoint}"
               StartPoint="{Binding Source={StaticResource BasicRainbowGradient}, Path=StartPoint}"
              GradientStops="{Binding Source={StaticResource BasicRainbowGradient}, Path=GradientStopCollection}" />
            </Border.Background>
</Border>
</UserControl>

This will give the LinearGradientBrush the elements defined in the "BasicRainbowGradient" defined in the UserControl.Resources.