Click here to Skip to main content
15,881,938 members
Articles / Desktop Programming / WPF

Creating and consuming a custom WPF control

Rate me:
Please Sign up or sign in to vote.
4.71/5 (44 votes)
1 Mar 20078 min read 238.7K   3.8K   111  
Creating and consuming a custom WPF control
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace ColorPicker
{
    #region ColorPickerControl CLASS
    /// <summary>
    /// A simple color picker control, with a custom event that uses
    /// the standard RoutedEventArgs. 
    /// <br/>
    /// NOTE: I also tried to create a custom event with custom inherited
    /// RoutedEventArgs, but this didnt seem to work, so this event is commented
    /// out. BUt if anyone knows how to do this please let me know, as as far as I know
    /// I am doing everything correctly
    /// </summary>
    public class ColorPickerControl : ListBox
    {
        #region InstanceFields
        //A RoutedEvent using standard RoutedEventArgs, event declaration
        //The actual event routing
        public static readonly RoutedEvent NewColorEvent =
                    EventManager.RegisterRoutedEvent("NewColor", RoutingStrategy.Bubble,
                    typeof(RoutedEventHandler), typeof(ColorPickerControl));

        //A RoutedEvent using standard custaom ColorRoutedEventArgs, event declaration
        
        ////the event handler delegate
        public delegate void NewColorCustomEventHandler(object sender, ColorRoutedEventArgs e);

        ////The actual event routing
        public static readonly RoutedEvent NewColorCustomEvent =
                    EventManager.RegisterRoutedEvent("NewColorCustom", RoutingStrategy.Bubble,
                    typeof(NewColorCustomEventHandler), typeof(ColorPickerControl));
        //************************************************************************

        //string array or colors
        private string[] _sColors = 
        {
            "Black", "Brown", "DarkGreen", "MidnightBlue", 
                "Navy", "DarkBlue", "Indigo", "DimGray",
            "DarkRed", "OrangeRed", "Olive", "Green", 
                "Teal", "Blue", "SlateGray", "Gray",
            "Red", "Orange", "YellowGreen", "SeaGreen", 
                "Aqua", "LightBlue", "Violet", "DarkGray",
            "Pink", "Gold", "Yellow", "Lime", 
                "Turquoise", "SkyBlue", "Plum", "LightGray",
            "LightPink", "Tan", "LightYellow", "LightGreen", 
                "LightCyan", "LightSkyBlue", "Lavender", "White"
        };
        #endregion
        #region Constructor
        /// <summary>
        /// Constructor for ColorPickerControl, which is a ListBox subclass
        /// </summary>
        public ColorPickerControl()
        {
            // Define a template for the Items, used the lazy FrameworkElementFactory
            // method
            FrameworkElementFactory fGrid = new
                FrameworkElementFactory(typeof(System.Windows.Controls.Primitives.UniformGrid));
            fGrid.SetValue(System.Windows.Controls.Primitives.UniformGrid.ColumnsProperty, 10);
            //update the ListBox ItemsPanel with the new ItemsPanelTemplate just created
            ItemsPanel = new ItemsPanelTemplate(fGrid);


            // Create individual items
            foreach (string clr in _sColors)
            {
                // Creat bounding rectnagle for items data
                Rectangle rItem = new Rectangle();
                rItem.Width = 10;
                rItem.Height = 10;
                rItem.Margin = new Thickness(1);
                rItem.Fill = (Brush)typeof(Brushes).GetProperty(clr).GetValue(null, null);
                //add rectangle to ListBox Items
                Items.Add(rItem);

                //add a tooltip
                ToolTip t = new ToolTip();
                t.Content = clr;
                rItem.ToolTip = t;

            }
            //Indicate that SelectedValue is Fill property of Rectangle item.
            //Kind of like an XPath query, this is the string name of the property 
            //to use as the the selected item value from the actual item data. The item
            //data being a Rectangle in this case
            SelectedValuePath = "Fill";
        }
        #endregion
        #region Events
        // Provide CLR accessors for the event
        public event RoutedEventHandler NewColor
        {
            add { AddHandler(NewColorEvent, value); }
            remove { RemoveHandler(NewColorEvent, value); }
        }

        // This method raises the NewColor event
        private void RaiseNewColorEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(NewColorEvent);
            RaiseEvent(newEventArgs);
        }

        // Provide CLR accessors for the event
        public event NewColorCustomEventHandler NewColorCustom
        {
            add { AddHandler(NewColorCustomEvent, value); }
            remove { RemoveHandler(NewColorCustomEvent, value); }
        }

        // This method raises the NewColorCustom event
        private void RaiseNewColorCustomEvent()
        {
            ToolTip t = (ToolTip)(SelectedItem as Rectangle).ToolTip;
            ColorRoutedEventArgs newEventArgs = new ColorRoutedEventArgs(t.Content.ToString());
            newEventArgs.RoutedEvent = ColorPickerControl.NewColorCustomEvent;
            RaiseEvent(newEventArgs);
        }
        //************************************************************************
        #endregion
        #region Overrides
        /// <summary>
        /// Overrides the OnSelectionChanged ListBox inherited method, and
        /// raises the NewColorEvent
        /// </summary>
        /// <param name="e">the event args</param>
        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            //raise the event with standard RoutedEventArgs event args
            RaiseNewColorEvent();
            //raise the event with the custom ColorRoutedEventArgs event args
            RaiseNewColorCustomEvent();
            //************************************************************************

        }
        #endregion
    }
    #endregion
    #region ColorRoutedEventArgs CLASS
    /// <summary>
    /// ColorRoutedEventArgs : a custom event argument class
    /// </summary>
    public class ColorRoutedEventArgs : RoutedEventArgs
    {
        #region Instance fields
        private string _ColorName = "";
        #endregion
        #region Consructor
        /// <summary>
        /// Constructs a new ColorRoutedEventArgs object
        /// using the parameters provided
        /// </summary>
        /// <param name="clrName">the color name string</param>
        public ColorRoutedEventArgs(string clrName)
        {
            this._ColorName = clrName;
        }
        #endregion
        #region Public properties
        /// <summary>
        /// Gets the stored color name 
        /// </summary>
        public string ColorName
        {
            get { return _ColorName; }
        }
        #endregion
    }
    #endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions