Wednesday, November 10, 2010

Quotes from the Coders - The Holy Application

The names below have been changed to protect the innocent...and the guilty!

Jose Says
"I feel like i'm working on a 'holy app'"
Cirrus Says
"Like it's full of security holes or something?"
Jose Says
"No like it's an application built for God"
Cirrus Says
"Why's that?"
Jose Says
"Because I'm using a method called 'SavePeople' and passing in a list of people to save"
Cirrus Says
"Hahaha...Maybe you should name the class to 'Salvation' just to mess with the original developer...if there's a method to delete people you could rename that to 'DamnPeople'.
Just make sure if you do use DamnPeople, you use the Description Attribute to make sure people know that you're removing these people from existence and if it doesn't have a splash screen...you could give it a literal 'Splash' screen"
Jose Says
"Of like holy water?"
Cirrus Says
"Better make it like baptism, since you're saving them after-all"

Tuesday, November 2, 2010

.NET 3.5 WPF Triggers - KeyDownTrigger

After having used Silverlight 4.0, i found myself getting frustrated using Silverlight 3.0, or even WPF of any version (lets face it, WPF just doesn't get the same loving the Silverlight does from the Microsoft Development Team) because of the absence of certain triggers and behaviors.

Since some of our projects rely on collaboration with people who don't have licenses to VS2010, we've had to keep those projects using .NET Framework 3.5. I suppose I ask for too much...but i always want more! And since the triggers and behaviors i wanted didn't work in 3.5, i decided to make more! Here's my code for the KeyDownTrigger:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Interactivity;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;

namespace ToP.Common.Triggers
{
    [DesignerCategory("Triggers")]
    public class KeyDownTrigger : TriggerBase<FrameworkElement>
    {

        /// <summary>
        /// Overides the OnAttached Method and adds our subscription to the PreviewKeyDown Event
        /// </summary>
        protected override void OnAttached ()
        {
            base.OnAttached();
            AssociatedObject.PreviewKeyDown += AssociatedObject_KeyDown;
        }

        /// <summary>
        /// Overides the OnDetaching Method and removes our subscription to the PreviewKeyDown Event
        /// </summary>
        protected override void OnDetaching ()
        {
            base.OnDetaching();
            AssociatedObject.PreviewKeyDown -= AssociatedObject_KeyDown;
        }

        [Category("KeyEvent Properties"), Description("Comma Delimitered list of Keys the trigger is contigent on")]
        public string Keys { 
            get
            {
                return (string)GetValue(KeysProperty);
            }
            set
            {
                SetValue(KeysProperty, value);
            }
        }
        public static readonly DependencyProperty KeysProperty =
            DependencyProperty.Register("Keys", typeof(string), typeof(KeyDownTrigger), new PropertyMetadata("None"));
        private List<Key> KeyList
        {
            get
            {
                return Keys.Split(',').Select(x => (Key)Enum.Parse(typeof(Key), x)).ToList();
            }
        }
        private List<ModifierKeys> ModifierList
        {
            get
            {
                return ModifierKeys.Split(',').Select(x => string.IsNullOrEmpty(x) ? System.Windows.Input.ModifierKeys.None : (ModifierKeys)Enum.Parse(typeof(ModifierKeys), x)).ToList();
            }
        }

        [Category("KeyEvent Properties"), Description("Comma Delimitered list of ModifierKeys the trigger is contigent on")]
        public string ModifierKeys
        {
            get
            {
                return (string)GetValue(ModifierKeysProperty);
            }
            set
            {
                SetValue(ModifierKeysProperty, value);
            }
        }
        public static readonly DependencyProperty ModifierKeysProperty =
            DependencyProperty.Register("ModifierKeys", typeof(string), typeof(KeyDownTrigger), new PropertyMetadata("None"));

        [Category("KeyEvent Properties"), Description("Sets the value of e.Handled for the PreviewKeyDown event. Default value is 'True'")]        
        public bool HandleKey
        {
            get
            {
                return (bool)GetValue(HandleKeyProperty);
            }
            set
            {
                SetValue(HandleKeyProperty, value);
            }
        }
        public static readonly DependencyProperty HandleKeyProperty =
            DependencyProperty.Register("HandleKey", typeof(bool), typeof(KeyDownTrigger), new PropertyMetadata(true));


        /// <summary>
        /// CallBack event to the PreviewKeyDown subscription that will InvokeActions 
        /// If the Key & Modifiers are found in our lists
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AssociatedObject_KeyDown (object sender, KeyEventArgs e)
        {
            if (KeyList.Contains(e.Key))
            {
                if (ModifierList.Count > 0)
                {
                    if (ModifierList.Contains(Keyboard.Modifiers))
                    {
                        InvokeActions(new TriggerKeys { Sender = AssociatedObject, Keys = e.Key, ModifierKeys = Keyboard.Modifiers });
                        e.Handled = HandleKey;
                    }
                }
                else
                {
                    InvokeActions(new TriggerKeys { Sender = AssociatedObject, Keys = e.Key, ModifierKeys = Keyboard.Modifiers });
                    e.Handled = HandleKey;
                }
            }
        }
    }

    public class TriggerKeys
    {
        public object Sender { get; set; }
        public Key Keys { get;  set; }
        public ModifierKeys ModifierKeys { get; set; }
    }
}

I was asked why i was using DependencyProperty(s), and it was simply to allow for those values to be databound to something. You'll also notice in the above code that we subscribe and unsubscribe to the Event. That can be done for ANY event, so you can use this idea to subscribe to any event you'd like!

This Trigger allows you to specify Keys, as well as ModifierKeys. It will also allow you to specifiy whether or not you want it to stop the RoutedEvent bubble after being triggered.

..And best yet, it works in both WPF & Silverlight, tested in .NET Framework 3.5 and .NET Framework 3.0!

Assuming we declare the namespace in the XAML as:
xmlns:triggers="clr-namespace:ToP.Common.Triggers"
The usage will be as follows:
<triggers:KeyDownTrigger HandleKey="True" Keys="Up" ModifierKeys="Control">
     <actions:FocusTarget TargetName="txtFirstName" />
/>
    </triggers:KeyDownTrigger>

Enjoy! I'll be posting my other Triggers shortly!

Flex Developers Wanted - SLC, UT

Full-time Positions for both a Flex Developer & Sr. Flex Developer are available in SLC, UT. Proficiency in Flex is a must, while someone with additional knowledge in Flash/Ajax/XML, and familiarity with web and database design is also desired.

10-10620

10-10619