FindControls for MasterPages

While working on an ASP.NET Website with a Master Page, I found a need for a function that could return all the dynamically created controls of a specific type. For instance, when you create a page full of textboxes, you’d like to be able to get/set their values. If you have ever worked with MasterPages, you’ll know how annoying it is to modify dynamically generated controls, since each control’s ID is modified to match the ContentPlaceHolder it resides in.

Below is the code for finding a series of controls based on a parent control (like a ContentPlaceHolder, or a Table)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq.Expressions;

/// <summary>
/// Extension Methods
/// </summary>
public static class Extensions
{
    #region Find Controls

    /// <summary>
    /// Finds a series of controls recursively
    /// </summary>
    /// <typeparam name="T">where T is of type System.Web.UI.Control</typeparam>
    /// <param name="parent">The parent control to search</param>
    /// <returns>A list of filtered controls based on a supplied type and predicate</returns>
    public static List<T> FindControls<T>(this System.Web.UI.Control parent) where T : System.Web.UI.Control {
        List<T> foundControls = new List<T>();
        FindControls<T>(parent, ref foundControls, null);
        return foundControls;
    }
    
    /// <summary>
    /// Finds a series of controls recursively, based on a predicate
    /// </summary>
    /// <typeparam name="T">where T is of type System.Web.UI.Control</typeparam>
    /// <param name="parent">The parent control to search</param>
    /// <param name="predicate">Filter returned controls based on a supplied predicate</param>
    /// <returns>A list of filtered controls based on a supplied type and predicate</returns>
    public static List<T> FindControls<T>(this System.Web.UI.Control parent, Func<T, bool> predicate) where T : System.Web.UI.Control {
        List<T> foundControls = new List<T>();
        FindControls<T>(parent, ref foundControls, predicate);
        return foundControls;
    }

    /// <summary>
    /// Finds a series of controls recursively, based on a predicate
    /// </summary>
    /// <typeparam name="T">where T is of type System.Web.UI.Control</typeparam>
    /// <param name="parent">The parent control to search</param>
    /// <param name="foundControls">A list of filtered controls based on a supplied type and predicate</param>
    /// <param name="predicate">Filter returned controls based on a supplied predicate</param>
    private static void FindControls<T>(System.Web.UI.Control parent, ref List<T> foundControls, Func<T, bool> predicate) where T : System.Web.UI.Control {
        if (parent == null) return;
        
        foreach (Control c in parent.Controls) {
            // Check this Control
            if (c is T && !c.GetType().IsSubclassOf(typeof(T))) {   // The Control isn't a Subclass of T (meaning, it's exactly type T)   
                if (predicate == null ? true : predicate((T)c)) {   // If the predicate isn't null, check the predicate's return values as well
                    foundControls.Add((T)c);                        // Control must be valid.
                }
            }
            
            // Check child Controls
            if (c.Controls.Count > 0)
                FindControls<T>(c, ref foundControls, predicate);
        }
    }

    #endregion Find Controls
}

It’s used like this: assume you have a list of TextBoxes that you’d ID’d as:
ID = “tbDynamic_23153″,
ID = “tbDynamic_23154″,
… etc …

that correspond to records in a database with ID=23153, ID=23154, etc; however, you also have design-time controls like “tbUserName” and “tbPassword”. If you want only the textboxes that start with “tbDynamic_”, then you’d do the following:

// Get the ContentPlaceHolder that the controls reside in...
ContentPlaceHolder cphContent = Master.FindControl("cphContent") as ContentPlaceHolder;

// Get all Textboxes that start with "tbDynamic_"...
List<TextBox> tbs = cphContent.FindControls<TextBox>(x => x.ID.StartsWith("tbDynamic_"));

// Then you can enumerate your database records and populate the textboxes...
for (var r in QueriedDatabaseRecords) {
    var tb = tbs.FirstOrDefault(x => x.ID = string.Format("tbDynamic_{0}", r.ID));
    
    if (tb != null)
        tb.Text = r.PropertyValue
}

It would be just as simple to get all CheckBoxes or TableRows. And it can be used when there isn’t a MasterPage, as well.

Quick update on ‘Hijinks at work’

Okay, so here’s an update on the Hijinks at work post.

The mark, who didn’t lock his computer yesterday, came into work this morning and started up his computer. I had the MMR app set in his startup folder, so when he logged in, the mouse started jumping every few seconds in a random direction. All of us in the room resisted the urge to laugh maniacally.

But then we noticed that he hadn’t tried to fix the problem yet. He acted oblivious to it. Only after about twenty minutes did he finally start to try and solve it. Now, the first thing I would have done was check for a remote session in VNC, and then the task manager for a rogue program. The mark, however, went to the control panel, and starting with the mouse setting, attempted to ‘fix it’.

At this point, the rest of us started sending emails to each other, since only I had line-of-sight to this guy’s monitor, so I could keep them informed. I watched as he searched through settings windows trying to solve it. He even picked up his mouse and shook it.

And then he shut down his computer, and left to go do other work.

Mission accomplished! And even better, since he didn’t solve it, it’ll happen again when he gets back.

Hijinxs at work

We have a co-worker who doesn’t understand that he’s got to lock his computer when he steps away from it, so we all decided to play a prank on him. Of course, there’s the standard “tape over laser under mouse” maneuver. Then there’s the “change his desktop backgrounds” or “change his Windows sounds” tactic. Mine was a bit more devious.

Below is the source code for a tiny program to run in the background, detectable only through task manager, that randomly moves the mouse pointer.

(Note: I use the .settings file because I can change the settings later to fine-tune them)

And here’s the Program.cs code. Create a Windows Form application (this is the important part – don’t create a Console app!), then delete the form and replace the Program.cs code with the code below. Compile and enjoy!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace mmr_e12
{
    /// <summary>
    /// Move Mouse Randomly Event 2012 Application
    /// </summary>
    static class Program
    {
        #region Settings

        /// <summary>
        /// The update speed for the Timer
        /// </summary>
        static int _MaxInterval = 2000;

        /// <summary>
        /// The maximum distance from the initial mouse position
        /// </summary>
        static int _MouseRadius = 100;

        /// <summary>
        /// Whether or not to use smooth mouse transitions
        /// </summary>
        static bool _UseSmoothness = true;

        /// <summary>
        /// The duration in seconds for the smooth mouse transition
        /// </summary>
        static double _SmoothnessDuration = 0.1;

        /// <summary>
        /// The perceived speed of the smooth transition
        /// (if Frame Time = 10ms, Perceived Speed = 100.0)
        /// </summary>
        static double _PerceivedSpeed = 500.0;

        #endregion Settings
        
        //**********************************



        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            try {
                // Create a Random Number Generator
                Random r = new Random();

                // Create a Windows Form Timer
                System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

                // Set the initial Interval low to get it going.
                timer.Interval = 100;

                // Set the Tick Event to update the mouse position
                timer.Tick += (sender, args) => {
                    
                    // Randomly determine change in position
                    var dx = r.Next(0, _MouseRadius * 2) - _MouseRadius;
                    var dy = r.Next(0, _MouseRadius * 2) - _MouseRadius;
                    
                    // Randomly determine next update interval
                    var z = (int)(_MaxInterval * r.NextDouble());
                    
                    // Prevent zero for update interval
                    if (z <= 0) z = 1;

                    // Move the cursor
                    if (_UseSmoothness)
                        SmoothMouseMove(dx, dy, _SmoothnessDuration);
                    else
                        Cursor.Position = new Point(Cursor.Position.X + dx, Cursor.Position.Y + dy);

                    // Update the Interval to increase the randomness
                    timer.Interval = z;
                };

                // Start the Timer
                timer.Start();

                // Run the Application Thread
                Application.Run();
            }
            catch (Exception Error) {
                // Show Error - no fun if failed!
                MessageBox.Show(string.Format("{0}", Error), "Application Error");
                
                // Exit application thread.
                Application.Exit();
            }
        }

        /// <summary>
        /// Smoothly transition the mouse pointer between it's current position and it's new position
        /// </summary>
        /// <param name="dx">Change in X Position</param>
        /// <param name="dy">Change in Y Position</param>
        /// <param name="durationInSeconds">The length of the transition time.</param>
        static void SmoothMouseMove(int dx, int dy, double durationInSeconds) {
            
            // Check for divide-by-zero & transition time
            if (!(durationInSeconds > 0))
                throw new ArgumentException("Transition Duration must be greater than 0.", "durationInSeconds");

            // Number of frames to "render"
            double frames = durationInSeconds * _PerceivedSpeed;

            // Length of pause time between frames
            int frameSleepLength = (int)((durationInSeconds / frames) * _PerceivedSpeed);

            // Create the change vector
            PointF vector = new PointF((float)(dx / frames), (float)(dy / frames));
            
            // Get the initial mouse position
            PointF mousePos = Cursor.Position;

            // Move through each frame of animation
            for (int i = 0; i < frames; i++) {
                
                // Set the new Cursor Position
                Cursor.Position = new Point((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y));

                // Sleep to transition over perceived time
                Thread.Sleep(frameSleepLength);
            }

        }
    }

    
}

Sending Wake-on-LAN Magic Packets from C#

I present, with little introduction, the MACAddress class. Within you will find simple test and conversion methods, with a single, simple to use method for sending a WOL ‘Magic’ Packet.

 

// MACAddress Class (Sending WOL 'Magic' Packets)
// Written by John Storer II (Feb 20, 2012)
//
// Feel free to use/modify this code as you wish, without liability.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SendWOLPacket
{
    public class MACAddress
    {
        /// <summary>
        /// Test a MACAddress byte Array.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static bool Test(byte[] macAddress) {
            if (macAddress == null) return false;
            if (macAddress.Length != 6) return false;

            return true;
        }

        /// <summary>
        /// Test a MACAddress string.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static bool Test(string macAddress) {
            var valid_chars = "0123456789ABCDEFabcdef";

            if (string.IsNullOrEmpty(macAddress)) return false;
            if (macAddress.Length != 12) return false;

            foreach (var c in macAddress) {
                if (valid_chars.IndexOf(c) < 0) {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Parse a MACAddress string into a byte array.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static byte[] Parse(string macAddress) {
            byte[] mac = new byte[6];

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress string.",
                    "macAddress",
                    null);

            for (var i = 0; i < 6; i++) {
                var t = macAddress.Substring((i * 2), 2);
                mac[i] = Convert.ToByte(t, 16);
            }

            return mac;
        }

        /// <summary>
        /// Attempt to parse a MACAddress string
        ///   without throwing an Exception.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <param name="Address"></param>
        /// <returns></returns>
        public static bool TryParse(string macAddress, out byte[] Address) {
            try {
                Address = Parse(macAddress);
                return true;
            }
            catch {
                Address = null;
                return false;
            }
        }

        /// <summary>
        /// Convert a byte array MACAddress to a string.
        /// </summary>
        /// <param name="macAddress"></param>
        /// <returns></returns>
        public static string ToString(byte[] macAddress) {
            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress byte array.",
                    "macAddress",
                    null);

            return BitConverter.ToString(macAddress).Replace("-", "");
        }


        /// <summary>
        /// Sends a Wake-On-LAN 'magic' packet to
        ///   the specified MACAddress string.
        /// </summary>
        /// <param name="macAddress"></param>
        public static void SendWOLPacket(string macAddress) {

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress string.",
                    "macAddress",
                    null);
            
            byte[] mac = Parse(macAddress);

            SendWOLPacket(mac);
        }

        /// <summary>
        /// Sends a Wake-On-LAN 'magic' packet to
        ///   the specified MACAddress byte array.
        /// </summary>
        /// <param name="macAddress"></param>
        public static void SendWOLPacket(byte[] macAddress) {

            if (!Test(macAddress))
                throw new ArgumentException(
                    "Invalid MACAddress byte array.",
                    "macAddress",
                    null);

            // WOL 'magic' packet is sent over UDP.
            using (UdpClient client = new UdpClient()) {

                // Send to: 255.255.255.0:40000 over UDP.
                client.Connect(IPAddress.Broadcast, 40000);

                // Two parts to a 'magic' packet:
                //     First is 0xFFFFFFFFFFFF,
                //     Second is 16 * MACAddress.
                byte[] packet = new byte[17 * 6];

                // Set to: 0xFFFFFFFFFFFF.
                for (int i = 0; i < 6; i++) {
                    packet[i] = 0xFF;
                }

                // Set to: 16 * MACAddress
                for (int i = 1; i <= 16; i++) {
                    for (int j = 0; j < 6; j++) {
                        packet[i * 6 + j] = macAddress[j];
                    }
                }

                // Send WOL 'magic' packet.
                client.Send(packet, packet.Length);
            }
        }

    }
}

Using this code is as simple as (assuming you have a form, a button named bSend and a text box named tbMACAddress):

private void bSend_Click(object sender, EventArgs e) {
    try {
        MACAddress.SendWOLPacket(tbMACAddress.Text);

        MessageBox.Show(
            string.Format("Packet Sent to '{0}'", tbMACAddress.Text));
    }
    catch (Exception Error) {
        MessageBox.Show(
            string.Format("Error:\n\n{0}", Error.Message), "Error");
    }
            
}

Why write a class to send WOL Packets? Mainly because I needed to wake up a PC at home remotely, if I really needed it. Also, someone here at work said, “I need to send WOL to this laptop, but I don’t have the Altiris Console handy,” to which I replied:

Challenge Accepted

Because who doesn't like a good challenge?

Some Myths about Introverts

Saw this on Google+ and had to share my insights on it.

Myth #1 – Introverts don’t like to talk.
This is not true. Introverts just don’t talk unless they have something to say. They hate small talk. Get an introvert talking about something they are interested in, and they won’t shut up for days.

[I am very much like that. Very true. I also have difficulty listening to people who take seemingly forever just to get to the point of their story. Spit it out already!]

Myth #2 – Introverts are shy.
Shyness has nothing to do with being an Introvert. Introverts are not necessarily afraid of people. What they need is a reason to interact. They don’t interact for the sake of interacting. If you want to talk to an Introvert, just start talking. Don’t worry about being polite.

[I think shyness does play a small part in it, but mostly it's mainly an excuse to stand back and investigate the situation.]

Myth #3 – Introverts are rude.
Introverts often don’t see a reason for beating around the bush with social pleasantries. They want everyone to just be real and honest. Unfortunately, this is not acceptable in most settings, so Introverts can feel a lot of pressure to fit in, which they find exhausting.

[Most people don't realize how difficult it is to resist the urge to speak our mind at all times. It can quickly make a social interaction intense.]

Myth #4 – Introverts don’t like people.
On the contrary, Introverts intensely value the few friends they have. They can count their close friends on one hand. If you are lucky enough for an introvert to consider you a friend, you probably have a loyal ally for life. Once you have earned their respect as being a person of substance, you’re in.

[Couldn't have said it better myself. I'm big with the social media. I have a G+ and a Facebook profile, plus a LinkedIn and probably much more than I can remember. I tend to "trim the fat" and remove those people who I have no desire or need to interact with, so that only those who have earned and deserve my attention receive it. It's also a good reason why I keep those profiles mostly private.]

Myth #5 – Introverts don’t like to go out in public.
Nonsense. Introverts just don’t like to go out in public FOR AS LONG. They also like to avoid the complications that are involved in public activities. They take in data and experiences very quickly, and as a result, don’t need to be there for long to “get it.” They’re ready to go home, recharge, and process it all. In fact, recharging is absolutely crucial for Introverts.

[Also very true. I prefer being at home, or being at a friends house. Being out in public tends to just slowly eat away at my patience. If I have to endure big crowds, I quickly become intensely focused on getting out of them, and getting to a 'safe' place.]

Myth #6 – Introverts always want to be alone.
Introverts are perfectly comfortable with their own thoughts. They think a lot. They daydream. They like to have problems to work on, puzzles to solve. But they can also get incredibly lonely if they don’t have anyone to share their discoveries with. They crave an authentic and sincere connection with ONE PERSON at a time.

[Agreed. It's actually quite difficult not to daydream whilst others are talking to me. Mental gymnastics. Not being able to share my thoughts and 'discoveries' with someone who gets me, who understands why I think the way I do, tends to make me slightly more nuts crazy insane. It's definitely a problem that goes down straight to the core of an introvert's personality.]

Myth #7 – Introverts are weird.
Introverts are often individualists. They don’t follow the crowd. They’d prefer to be valued for their novel ways of living. They think for themselves and because of that, they often challenge the norm. They don’t make most decisions based on what is popular or trendy.

[I think, therefore I am. And I definitely think I'm strange. But since I tend to surround myself with people that understand me, I guess I become the relative norm!]

Myth #8 – Introverts are aloof nerds.
Introverts are people who primarily look inward, paying close attention to their thoughts and emotions. It’s not that they are incapable of paying attention to what is going on around them, it’s just that their inner world is much more stimulating and rewarding to them.

[True. Most of the time the stories I create in my own head are much more fantastic than those of others. And unfortunately, when I find a story that captivates me, it's a difficult job to pay attention to other, less interesting conversations.]

Myth #9 – Introverts don’t know how to relax and have fun.
Introverts typically relax at home or in nature, not in busy public places. Introverts are not thrill seekers and adrenaline junkies. If there is too much talking and noise going on, they shut down. Their brains are too sensitive to the neurotransmitter called Dopamine. Introverts and Extroverts have different dominant neuro-pathways. Just look it up.

[Reading the Wikipedia entry on that particular topic leads me to believe that this response is backwards; that extroverts are more sensitive to dopamine levels, which is they they seek out stimulation instead of being content. Otherwise, yes, we prefer to stay at home to relax.]

Myth #10 – Introverts can fix themselves and become Extroverts.
A world without Introverts would be a world with few scientists, musicians, artists, poets, filmmakers, doctors, mathematicians, writers, and philosophers. That being said, there are still plenty of techniques an Extrovert can learn in order to interact with Introverts. (Yes, I reversed these two terms on purpose to show you how biased our society is.) Introverts cannot “fix themselves” and deserve respect for their natural temperament and contributions to the human race. In fact, one study (Silverman, 1986) showed that the percentage of Introverts increases with IQ.

[I don't know why other people would see introversion as a bad thing. Introverts tend to be smarter and better adjusted to the world around them, especially since we choose with such care where and with whom we spend our time with.]