Friday, August 2, 2013

Circular ListBox

I've been working with Silverlight, and I have been challenging myself to make my code cleaner for the controls and have the computer/system do more of the thinking. It's definitely a challenge to keep making the code smaller and cleaner for each of my controls.

Was playing with a few codes and putting the ideas together:

Today, merging a Simple Radial Panel and a more advanced Radial Panel with styling the way a list is presentedI'm not listing the code for the RadialPanel, the links explain the process a lot better than I can.

Below is a screenshot of the final styled list.


Circular ListBox
This was a less intimidating way for me to look into styling with more code behind and try to cut down on the amount of XAML I have in any one control (data templates, etc).

The first step was to create the RadialPanel class (from this Blog Post).

Once defined, I was able to set a new ItemsPanelTemplate in a style that set the RadialPanel as the base for the ListBox - as well as set a DataTemplate for the list items so I could read the information straight from a List<>.

 <Style x:Key="RoundListOne" TargetType="ListBox">
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <local:RadialPanel Width="350" Height="350" RenderTransformOrigin="0.5,0.5">
                        <local:RadialPanel.RenderTransform>
                            <CompositeTransform ScaleX="0.9" ScaleY="0.9"/>
                        </local:RadialPanel.RenderTransform>
                    </local:RadialPanel>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" Tag="{Binding Path=colorValue}">
                        <Ellipse Name="colorSwatch" HorizontalAlignment="Center"
                                Width="30" Height="30" Fill="{Binding Path=colorValue}"/>
                        <TextBlock HorizontalAlignment="Center" Foreground="Gray"
                                Text="{Binding Path=colorName}"
                                VerticalAlignment="Center" Margin="5,0,0,0"/>
                    </StackPanel>
                   
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="ListBoxItemContainerStyle" TargetType="ListBoxItem">
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
    </Style>


Below is the XAML for the Color Wheel - it's just a ListBox

<Grid x:Name="LayoutRoot">
        <ListBox Name="CircularList"
            ItemContainerStyle="{StaticResource ListBoxItemContainerStyle}"
            Style="{StaticResource RoundListOne}"
            HorizontalAlignment="Center" VerticalAlignment="Center"
            Margin="10,19,164,18" UseLayoutRounding="False" Width="466" Height="443"
            SelectedValuePath="{Binding Path=colorValue}" BorderBrush="{x:Null}"
            SelectedValue="{Binding Path=colorValue}" SelectionChanged="changePreview" >
        </ListBox>
        <TextBox HorizontalAlignment="Left" Name="ColorPreview"
            TextWrapping="Wrap" Text="Color Formula Here"
            VerticalAlignment="Top" Margin="396,207,0,0"
            Width="136" Height="38" TextAlignment="Center"/>
    </Grid>



The code behind for the ListBox:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;


namespace PracticeControls
{
    public partial class CircularPicker : UserControl
    {
        public CircularPicker()
        {
            // Required to initialize variables
            InitializeComponent();
           
            this.Loaded += new RoutedEventHandler(populateList);
        }
       
        void populateList(object sender, RoutedEventArgs e)
        {
            PracticeData practiceData = new PracticeData();
           
            CircularList.DataContext = practiceData;
            CircularList.ItemsSource = practiceData._colorChoices;
            CircularList.SelectedValuePath = "colorValue";
        }

        private void changePreview(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            // TODO: Add event handler implementation here.
            var colorchoice = CircularList.SelectedItem;
            var colorname = CircularList.SelectedValue;
            ColorPreview.Text = colorname.ToString();
           
            string backgroundColor = colorname.ToString();
            var backgroundValue = backgroundColor.Replace("#",string.Empty);
           
            byte a = (byte)(Convert.ToUInt32(backgroundValue.Substring(0,2),16));
            byte r = (byte)(Convert.ToUInt32(backgroundValue.Substring(2,2),16));
            byte g = (byte)(Convert.ToUInt32(backgroundValue.Substring(4,2),16));
            byte b = (byte)(Convert.ToUInt32(backgroundValue.Substring(6,2),16));
           
            SolidColorBrush previewBrush = new SolidColorBrush(Color.FromArgb(a,r,g,b));
            ColorPreview.Background = previewBrush;
        }
    }
}


The data is a very basic List< >:
 
public class ColorValues
        {
            public string colorValue {get; set;}
            public string colorName {get; set;}
        }
       
        private readonly List<ColorValues> _colorValues = new List<ColorValues>
        {
            new ColorValues {colorValue="#FFFF0000",colorName="Red"},
            new ColorValues {colorValue="#FFFF3300",colorName="Vermillion"},
            new ColorValues {colorValue="#FFFF6600",colorName="Amber"},
            new ColorValues {colorValue="#FFFFCC00",colorName="Gold"},
            new ColorValues {colorValue="#FFFFFF00",colorName="Yellow"},
            new ColorValues {colorValue="#FFCCFF00",colorName="Apple"},
            new ColorValues {colorValue="#FF66FF00",colorName="Chartreuse"},
            new ColorValues {colorValue="#FF33FF00",colorName="Lime"},
            new ColorValues {colorValue="#FF00FF00",colorName="Green"},
            new ColorValues {colorValue="#FF00FF33",colorName="Mint"},
            new ColorValues {colorValue="#FF00FF66",colorName="Jade"},
            new ColorValues {colorValue="#FF00FFCC",colorName="Turquoise"},
            new ColorValues {colorValue="#FF00FFFF",colorName="Cyan"},
            new ColorValues {colorValue="#FF00CCFF",colorName="Azure"},
            new ColorValues {colorValue="#FF0066FF",colorName="Sapphire"},
            new ColorValues {colorValue="#FF0033FF",colorName="Cobalt"},
            new ColorValues {colorValue="#FF0000FF",colorName="Blue"},
            new ColorValues {colorValue="#FF6600FF",colorName="Violet"},
            new ColorValues {colorValue="#FF9900FF",colorName="Purple"},
            new ColorValues {colorValue="#FFCC00FF",colorName="Orchid"},
            new ColorValues {colorValue="#FFFF00FF",colorName="Magenta"},
            new ColorValues {colorValue="#FFFF00CC",colorName="Fuchsia"},
            new ColorValues {colorValue="#FFFF0066",colorName="Carmine"},
            new ColorValues {colorValue="#FFFF0033",colorName="Scarlet"},
        };
       
        public List<ColorValues> _colorChoices
        {
            get {return _colorValues;}
        }
       
        private ColorValues _colorOptions;
       
        public ColorValues ColorOptions
        {
            get {return _colorOptions;}
            set
            {
                _colorOptions = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ColorValues"));
            }
           
        }


You can see the working example here. Going to be playing with this idea some more, not sure with what or how but so far it's been fun customizing the basic ListBox this way.


No comments:

Post a Comment