Pluralsight

Or is it Pluralsite?  They seem to use both.  In any event, I finished an audition for Pluralsight yesterday.  It was a 10 minute demo of slides and code.  It was a really interesting process and makes me appreciate what it takes to do it.  Lesson learned include:

1) Script the slide deck – down to the pauses for breathing.  I first tried to do it without any help – epic failure.  I then tried to do it with bullet points – failure.  After about an hour of takes and re-takes of the first slide, I surrendered and scripted everything.  I then could get through the slide deck in about 5 takes per slide.

2) Everything is editable.  In the beginning, once I screwed up, I would stop and restart.  Then, I realized that I was re-recoding my good content so I started to place a break after my screw up, re-record and then edit out the the screw-up.  I learned that to do this effectively, I need splice points that don’t look like splice points so I can screw up without losing the good stuff.

3) Speaking of which, I spent waaaay too much time in Camtasia, the video editing software.  Just learning how to use that took a better part of my Sunday.  Once I figured it out some, it was great to use.

4) I did the code in about 6 takes – and it shows.  I did not script my code, instead I treated it more like the classes I teach with the occasional flub and mistyping (And I technical error that Rob Seder sent me).  I also typed my code versus drag and dropping code blocks (or using code snippets).  I talked to different people and each have a different option on this – I find presentations more interesting with typing, even if it is not as smooth as a professional typist.  Some people like the typing (you can really hear my mechanical keyboard in the video), others do not.  Derik Whittaker was kind enough to do a full-on, no holds-barred review of what I did suggested in speeding up time for the longer typing moments – which I didn’t even think of.

5) Speaking of Derik, he has done a couple of courses and he showed me how to prepare for a course.  If I get picked up, I will implement much of his methodology.  Basically, you can’t be too organized for teaching a Pluralsight course.  Derik has a 3 monitor setup when recording and he scripts everything in one-note.  He also does much of his effects in editing, so he is not concentrating on that stuff when recording.

6) Speaking of getting picked up, there is a TON of content in the pipeline.  I am pitching .NET best practices and there are several other courses that have some overlap (some already in prod) so I am curious that if the course gets green-lighted, how many people will actually watch it.

In any event, it was an interesting process and since I learned something, it was worth it.  If I get picked up, I will take a hiatus from blogging because my free time will be spent on that.  Seems like a worthwhile adventure, no?

Advertisements

WPF Event Bubbling and Routed Events

Consider a User Control with a single button on it:

  1. <UserControl x:Class="Tff.ButtonClickBubble.MainUserControl"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
  6.              mc:Ignorable="d" Height="100" Width="100">
  7.     <Grid Background="Red" Margin="0,0,0,0">
  8.         <Button x:Name="MainButton"
  9.             Content="Push Me" HorizontalAlignment="Left"
  10.                 Margin="19,36,0,0" VerticalAlignment="Top"
  11.                 Width="62" Height="25"
  12.                 Click="MainButton_Click"/>
  13.     </Grid>
  14. </UserControl>

 

In the code behind, the click event shows a dialog

  1. public partial class MainUserControl : UserControl
  2. {
  3.     public MainUserControl()
  4.     {
  5.         InitializeComponent();
  6.     }
  7.  
  8.     private void MainButton_Click(object sender, RoutedEventArgs e)
  9.     {
  10.         MessageBox.Show(e.Source.ToString());
  11.     }
  12. }

After hitting F6 so the control will show in my toolbox, I then put an instance of that control on a basic page like so:

  1. <Window
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         xmlns:local="clr-namespace:Tff.ButtonClickBubble" x:Class="Tff.ButtonClickBubble.MainWindow"
  5.         Title="MainWindow" Height="236" Width="184">
  6.     <Grid x:Name="MainGrid" Background="AliceBlue">
  7.         <local:MainUserControl HorizontalAlignment="Left" Margin="35,44,0,0" VerticalAlignment="Top"/>
  8.     </Grid>
  9. </Window>

 

When I hit F5, I get the expected MessageBox:

image

So now I want the main window to intercept that button click and pop its own dialog box.  The Window class does not have a click event – rather it has a mousedown event.  By adding the mouse down event hander to the main window, I have this:

  1. <Window
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         xmlns:local="clr-namespace:Tff.ButtonClickBubble" x:Class="Tff.ButtonClickBubble.MainWindow"
  5.         Title="MainWindow" Height="236" Width="184" MouseDown="Window_MouseDown">

 

And in the code behind:

  1. private void Window_MouseDown(object sender, MouseButtonEventArgs e)
  2. {
  3.     MessageBox.Show(e.Source.ToString());
  4. }

 

Unfortunately, that doesn’t work.  The button click event swallows the event so the MouseDown only fires on the part of the window where the button is not:

imageimage

So I went into StackOverflow and I found this post that I think describes the problem.  So I changed the MouseDown to the PreviewMouseDown event and sure enough, I can handle the event from the main screen:

image

But the ClickEvent on the button is not being fired.  I then added a e.handled = false but that did not help:

  1. private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  2. {
  3.     MessageBox.Show(e.Source.ToString());
  4.     e.Handled = false;
  5. }

 

So the answer marked as correct on stack overflow does apply here.  The answer below the marked as correct answer is relevant.  I tried to add a handler to the Grid (Windows don’t have AddHandler methods) like this:

  1. public MainWindow()
  2. {
  3.     InitializeComponent();
  4.     MainGrid.AddHandler(MouseDownEvent, new MouseButtonEventHandler(MainGrid_MouseDown), true);
  5. }
  6.  
  7. private void MainGrid_MouseDown(object sender, MouseButtonEventArgs e)
  8. {
  9.     MessageBox.Show(e.Source.ToString());
  10. }

 

The problem is that it is not working either.  Fortunately, the answer below THAT one does work:

  1. <Window
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         xmlns:local="clr-namespace:Tff.ButtonClickBubble" x:Class="Tff.ButtonClickBubble.MainWindow"
  5.         Title="MainWindow" Height="236" Width="184" >
  6.     <Grid x:Name="MainGrid" Background="AliceBlue" Button.Click="MainGrid_MouseDown">
  7.         <local:MainUserControl HorizontalAlignment="Left" Margin="35,44,0,0" VerticalAlignment="Top"/>
  8.     </Grid>
  9. </Window>

 

And

  1. public partial class MainWindow : Window
  2. {
  3.     public MainWindow()
  4.     {
  5.         InitializeComponent();
  6.     }
  7.  
  8.     private void MainGrid_MouseDown(object sender, RoutedEventArgs e)
  9.     {
  10.         MessageBox.Show(e.Source.ToString());
  11.     }
  12.  
  13. }

 

They key thing is wiring up the Grid like this:  Button.Click="MainGrid_MouseDown"

SSIS Packages

Dear Future Jamie:

 

If you have to set up a SSIS package in the future and you need to use non-integrated security – you can’t save the password in the package itself.  You need to create a .config file and place it on a central location on the data server.  You can then enter in the Password into that file and the job will run.

 

Love Current Jamie

Meetup’s API

One of the things I want to do at this year’s TRINUG’s code camp is to have self-service kiosks the way that Mark Wilson did for the Charlotte code camp.  To that end, I took a look at Justin Saraceno’s awesome project on Github of consuming the Meetup API to do the door prize at TRINUG.

Instead of javascript, I am going to write the app in C# and side-load it onto a couple of kiosks.  To that end, I built a web request/response to the meetup API:

  1. static void GetMeetupInformation()
  2. {
  3.     String url = @"https://api.meetup.com/2/event/125656692?key=&quot; + _apiKey;
  4.     WebRequest request = WebRequest.Create(url);
  5.     request.ContentType = @"application/json; charset=utf-8";
  6.  
  7.     WebResponse response = (HttpWebResponse)request.GetResponse();
  8.     using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  9.     {
  10.         String responseText = reader.ReadToEnd();
  11.         Console.WriteLine(responseText);
  12.     }
  13. }

 

I then pushed the response text into JSONToCSharp and got the following classes:

  1. namespace Tff.MeetUpAPI
  2. {
  3.     public class Member
  4.     {
  5.         public string name { get; set; }
  6.         public int member_id { get; set; }
  7.     }
  8.  
  9.     public class MemberPhoto
  10.     {
  11.         public string photo_link { get; set; }
  12.         public string thumb_link { get; set; }
  13.         public int photo_id { get; set; }
  14.         public string highres_link { get; set; }
  15.     }
  16.  
  17.     public class Event
  18.     {
  19.         public string id { get; set; }
  20.         public object time { get; set; }
  21.         public string event_url { get; set; }
  22.         public string name { get; set; }
  23.     }
  24.  
  25.     public class Venue
  26.     {
  27.         public int id { get; set; }
  28.         public string zip { get; set; }
  29.         public double lon { get; set; }
  30.         public bool repinned { get; set; }
  31.         public string name { get; set; }
  32.         public string state { get; set; }
  33.         public string address_1 { get; set; }
  34.         public double lat { get; set; }
  35.         public string city { get; set; }
  36.         public string country { get; set; }
  37.     }
  38.  
  39.     public class Group
  40.     {
  41.         public int id { get; set; }
  42.         public double group_lat { get; set; }
  43.         public double group_lon { get; set; }
  44.         public string join_mode { get; set; }
  45.         public string urlname { get; set; }
  46.     }
  47.  
  48.     public class Result
  49.     {
  50.         public string response { get; set; }
  51.         public Member member { get; set; }
  52.         public MemberPhoto member_photo { get; set; }
  53.         public object created { get; set; }
  54.         public Event @event { get; set; }
  55.         public object mtime { get; set; }
  56.         public int guests { get; set; }
  57.         public int rsvp_id { get; set; }
  58.         public Venue venue { get; set; }
  59.         public Group group { get; set; }
  60.         public string comments { get; set; }
  61.     }
  62.  
  63.     public class Meta
  64.     {
  65.         public string lon { get; set; }
  66.         public int count { get; set; }
  67.         public string link { get; set; }
  68.         public string next { get; set; }
  69.         public int total_count { get; set; }
  70.         public string url { get; set; }
  71.         public string id { get; set; }
  72.         public string title { get; set; }
  73.         public long updated { get; set; }
  74.         public string description { get; set; }
  75.         public string method { get; set; }
  76.         public string lat { get; set; }
  77.     }
  78.  
  79.     public class RootObject
  80.     {
  81.         public List<Result> results { get; set; }
  82.         public Meta meta { get; set; }
  83.     }
  84.  
  85.  
  86. }

 

I then created a data structure that contains only the data that I care about and build a quick translator function:

  1. private static Attendee CreateAttendeeFromMember(Result result)
  2. {
  3.     Attendee attendee = new Attendee();
  4.     attendee.MemberId = result.member.member_id;
  5.     attendee.Name = result.member.name;
  6.     if (result.member_photo != null)
  7.     {
  8.         attendee.PhotoUrl = result.member_photo.thumb_link;
  9.     }
  10.     
  11.     return attendee;
  12. }

 

Putting it together, I now have a way of parsing the event and getting a list of the attendees that I can use on the signin page:

  1. static List<Attendee> GetMeetupAttendees()
  2. {
  3.     List<Attendee> attendees = new List<Attendee>();
  4.  
  5.     String url = @"https://api.meetup.com/2/rsvps/?rsvps=yes&event_id=125656692&key=&quot; + _apiKey;
  6.     WebRequest request = WebRequest.Create(url);
  7.     request.ContentType = @"application/json; charset=utf-8";
  8.  
  9.     WebResponse response = (HttpWebResponse)request.GetResponse();
  10.     using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  11.     {
  12.         String responseText = reader.ReadToEnd();
  13.         var outObject = JsonConvert.DeserializeObject<RootObject>(responseText);
  14.  
  15.         Attendee attendee = null;
  16.         foreach (Result result in outObject.results)
  17.         {
  18.             attendee = CreateAttendeeFromMember(result);
  19.             attendees.Add(attendee);
  20.         }
  21.     }
  22.  
  23.     return attendees;
  24. }

 

And in action:

  1. Console.WriteLine("Start");
  2. List<Attendee> attendees = GetMeetupAttendees();
  3.  
  4. foreach (Attendee attendee in attendees)
  5. {
  6.     Console.WriteLine(attendee.Name);
  7. }
  8. Console.WriteLine("End");
  9. Console.ReadKey();

 

gives:

image

NInject Example

I started looking at NInject do handle the dependency injection that I normally do by hand.   To that end, I spun up the project that I used for my last foray into the world of dependency injection:

  1. public interface IAnimal
  2. {
  3.     void Talk();
  4.     void Eat();
  5. }

 

And

 

  1. public class Elephant: IAnimal
  2. {
  3.     public void Talk()
  4.     {
  5.         Console.WriteLine("Trumpet");
  6.     }
  7.  
  8.     public void Eat()
  9.     {
  10.         Console.WriteLine("Yummy Peanuts");
  11.     }
  12. }
  13.  
  14. public class Seal: IAnimal
  15. {
  16.     public void Talk()
  17.     {
  18.         Console.WriteLine("Ark Ark");
  19.     }
  20.  
  21.     public void Eat()
  22.     {
  23.         Console.WriteLine("Yummy Fish");
  24.     }
  25. }

 

Mow, instead of using Activator.CreateInstance, I am going to use NInject to do the mapping,  To that end, I installed NInject via NuGet

image

I then coded up the example for the on-line tutorial using the StandardKernal class like so

  1. static void Main(string[] args)
  2. {
  3.     IKernel kernel = new StandardKernel();
  4.     IAnimal animal = kernel.Get<Elephant>();
  5.     animal.Talk();
  6.     animal.Eat();
  7.     Console.ReadKey();
  8. }

 

and sure enough

image

So this is good stuff.  I think NInject and MOQ are my two favorite new tools in the toolbox…