Wednesday, April 28, 2010

Silverlight Color Picker ComboBox (DropDownList)

During a Silverlight project I finished up a while ago I needed to create a "simple" Color Picker ComboBox (or DropDownList for us ASP.NET Developers).  By "simple" I mean limited to only a handful of colors, not as complex as something like Paint.NET (read PhotoShop) would provide.  This is the easiest solution that I found.

The first thing you need to know is that the ComboBox has an ItemTemplate.  This template allows you to completely control the look and feel of each entry in the ComboBox.  From simple things like binding to a property to change the background color (hint hint, that is what we are about to do), to more complex things like changing the entire template based on the type of class being bound to this item in the ComboBox (ex: the ComboBox is bound to a list of "fruits" some are apples and some are bananas.  The apples all use one template, the bananas use a completely different template - powerful).

We'll be binding this ComboBox to a list of strings.  Each string we be the Hex representation of an eventual Color in the ComboBox.  Here is the ViewModel that holds the List (and "SelectedColor" property that holds the currently selected color)


   10 public class MyViewModel
   11 {
   12     public string SelectedColor { get; set; }
   13 
   14     public IList<string> Colors { get; set; }
   15 
   16     public MyViewModel()
   17     {
   18         Colors = new List<string>() {
   19             "000000",//black
   20             "404040",//gray
   21             "808080",//light gray
   22             "FFFFFF",//white
   23             "402000",//brown
   24             "FF0000",//red
   25             "FF8000",//orange
   26             "FFFF00",//yellow
   27             "00FF00",//green
   28             "008000",//dark green
   29             "0080FF",//light blue
   30             "0000FF",//blue
   31             "400080",//purple
   32             "8000FF",//light purple
   33             "FF00FF",//pink
   34             "FF80FF"//light pink
   35             };
   36     }
   37 }


Then we'll need to create a new IValueConverter that will assist us in binding the strings to the ComboBox (and more specifically the Background Brush in the ItemTemplate).  We can call the IValueConverter simply, StringToBrushConverter.  IValueConverter is a fairly easy interface to implement, it only has two methods, Covert and ConvertBack.  (As far as I can tell, the ColorConverter class is not in Silverlight yet, so the code is a bit messy for converting back and forth, but it'll do.)


   10 public class StringToBrushConverter : IValueConverter
   11 {
   12     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   13     {
   14         string colorString = value as string;
   15         if (String.IsNullOrEmpty(colorString))
   16             return new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
   17 
   18         try
   19         {
   20             Color c = new Color();
   21             c.A = 255;
   22             c.R = byte.Parse(colorString.Substring(0, 2), NumberStyles.HexNumber);
   23             c.G = byte.Parse(colorString.Substring(2, 2), NumberStyles.HexNumber);
   24             c.B = byte.Parse(colorString.Substring(4, 2), NumberStyles.HexNumber);
   25 
   26             return new SolidColorBrush(c);
   27         }
   28         catch
   29         {
   30             return new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
   31         }
   32     }
   33 
   34     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   35     {
   36         //NOTE "value as Color" - doesn't work
   37 
   38         if (value is Color)
   39         {
   40             Color c = (Color)value;
   41             return c.ToString();
   42         }
   43 
   44         return "000000";
   45     }
   46 }


Okay, so we've got our data, and the converter, so now we just need to wire it up.  First we add the StringToBrushConverter as a Resource for the UserControl.  Then we define the ComboBox's ItemTemplate.  Now at first I thought I could use a simple Canvas in the ItemTemplate and set its Background to a SolidColorBrush that was the same color as the string, but for some reason in my project that was just not working.  The Canvas was not aligning properly in the ComboBox.  When I pulled the code out and put it into its own solution, it worked fine.  I ended up Placing a Grid in the ItemTemplate and setting its background color, then placing a single TextBlock inside the grid and setting its Height and Width to size the grid....  try the Canvas first, but if that doesn't work for you I've included the "alternate solution".

Note the use of "Binding ." in the Binding statement of the Background property.  That means Bind to the "entire" current DataContext itself and not a property of the current DataContext.  (the ComboBox binds to the "Colors" collection, each Item binds to a individual string in the collection, so saying "Binding ." is saying bind to that string.  A more common scenario might be to bind to a List of Employees, and bind each Item to the "Name" property.  If you said "Binding ." in that case, you would be binding to a single Employee instance in the Employees collection)


   10 public partial class MainPage : UserControl
   11 {
   12     public MainPage()
   13     {
   14         InitializeComponent();
   15 
   16         this.Loaded += (s, e) =>
   17         {
   18             this.DataContext = new MyViewModel();
   19         };
   20     }
   21 }


   10 <UserControl x:Class="Adh.Silverlight.MainPage"
   11    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   12    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   13    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   14    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   15    xmlns:adh="clr-namespace:Adh.Silverlight"
   16    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   17     <UserControl.Resources>
   18         <adh:StringToBrushConverter x:Key="StringToBrushConverter">adh:StringToBrushConverter>
   19     UserControl.Resources>
   20     <Grid x:Name="LayoutRoot">
   21         <ComboBox ItemsSource="{Binding Colors}" SelectedItem="{Binding Color, Mode=TwoWay}" Width="140" Height="24">
   22             <ComboBox.ItemTemplate>
   23                 <DataTemplate>
   24                     <Canvas Background="{Binding ., Converter={StaticResource StringToBrushConverter}}" Width="100" Height="18">Canvas>
   25                    
   28                 DataTemplate>
   29             ComboBox.ItemTemplate>
   30         ComboBox>
   31     Grid>
   32 UserControl>


And there it is, that's all there is to it.  Hope you can find a use for this somewhere.

-

Sunday, April 11, 2010

Wisconsin Film Festival

My First Point of 2010!  I'm not sure what happened to my "top 5" lists from 2009, those were suppose to be posts at one time, but I never got around to writing them.  The lists were made, (highlights include New Super Mario Bros and Uncharted 2) but the posts were never written.  I've also been really busy this year with preparation for GDC and Microsoft's MIX 10 conference...  those probably should have been blogs posts as well, hu?

So I guess I'll start this year off with the Wisconsin Film Festival.  This is the first year that I've actually bought tickets before the night of the movie!  In the past, the movies I've wanted to see have always sold out early, so I've always had to do "Rush" tickets and luck out by getting one at the door.  It hasn't failed me yet, and hopefully I can keep that streak alive this year because there are a few on my list that are already sold out.  For the most part however, I'll already have my tickets!


Here is the list:

The Art of the Steal, (art and politics in Philadelphia)
Wed, 7:00pm, MMoCA --- rush only
(Sun, 1:30 MMoCA)
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3006#

OSS 117: Lost in Rio (james bond style comedy)
Wed, 10pm, Orpheum
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3122#


One Crazy Ride (motorcycle ride through remote india)
Thr, 7:30pm, Play Circle --- rush only
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3119#

Point Traverse (remote town life)
Thr, 9:30-11:30, Chazen
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3130


The Scenesters (comedy about filming crime scenes)
Fri, 10pm, Wis Union
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3143#


Sweetgrass (modern cowboy)
Sat, 11am, Orpheum
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3163#

Special When Lit (Pinball Movie - must see)
Sat, 1:00pm, Chazen
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3156#

Passenger Side (comedy)
Sat, 6pm-7:30pm, Wis Union
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3127#


Paddle to Seattle (journey from Alaska to Seattle)
Sun, 1:30pm, Wis Union
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?EventNumber=3125&notepg=1#

Beyond the Pole ("green" journey to the north pole)
Sun, 6pm, Wis Union
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3015


Honorable Mentions


Movies I liked the sound of but will probably not have time for....

Agrarian Utopia, (rice farming is a hard life)
Sun, 1:30 Chazen
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3004#

Black (short. thriller)
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/prognote.php?ProgCode=SHX02&notepg=1

Cannon Falls (short. wisconsin recording studio)
Sun 1:30pm, UW Cinematheque
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3021

The Girl with the Dragon Tattoo (Sweden Murder investigation)
Sat, 7:30pm, Orpheum
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3061

Human Terrain (Iraqi village training in California)
Fri, 5pm, Chazen
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3076#

Last Train Home (families on chinese new year)
Fri, 1pm, Stage Door
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3084#

Scrap (bishops castle, scrap metal projects)
Sun, 6:30pm, Monona Terrace
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3144#

A Matter of Size (comedy about Israeli Sumo wrestling)
Sat, 1pm, Orpheum
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3099#

Terribly Happy (thriller, experimental)
Sun, 4:30pm, Orpheum
http://filmguide.wifilmfest.org/tixSYS/2010/xslguide/eventnote.php?notepg=1&EventNumber=3166#



Hope to see you at the show!

Saturday, December 19, 2009

ADH .NET Helper Library

(please link to this page using http://tinyurl.com/adhlib)

I plan to slowly put this helper library together over time. There are a lot of helper classes and libraries out there - the goal of this project is to make the source classes/files easy to extract a single file at a time for use within your projects. The entire libraries/assemblies can still be referenced as well, but sometimes it is easier to just copy a single file. Enjoy!


source code download: http://aaronhoffman.googlecode.com/files/AdhLibv3.5.0.zip



Live Test Sites (also included in source code):

Silverlight Navigation: http://tinyurl.com/adhlibsl



Articles Highlighting Project Features:


(I will link to future articles here)


-Aaron