October 2008 - Posts
I find it really strange that there are code snippets for Dependency Properties but not Routed Events! Routed Events allow events to tunnel (preview) events up a visual tree and bubble them back down the visual tree. Any control along the tree can subscribe to these events and handle them. You can also choose to see events even if they have been handled.
This makes RoutedEvents very nice for use in XAML! For example, lets say you have a StackPanel and you want to know about any button clicks happening in that panel, you could simply use the following XAML:
<StackPanel ButtonBase.Click="MyButtonEventHandler">
<Button Height="50" Content="Button 1" />
<Button Height="50" Content="Button 2" />
<Button Height="50" Content="Button 3" />
<Button Height="50" Content="Button 4" />
</StackPanel>
Now when any one of the buttons are clicked, the stack panel will receive notification. Just like Attached Properties, the stack panel does not need to have a Click event. If a button does not exist inside of the stack panel there is no problem, you just won't receive any notification. The buttons do not even have to be direct children of the stack panel for this to work so if we wanted we could put them inside of another stack panel or any other content control.
I really think it strange that there was no snippet for Routed Events (being as handy as they are) so I took the time to write one.
Lets make a code snippet for a Routed Event, here is how:
Create a Custom Snippet
- Find a snippet you plan to modify in the Manage Snippets Dialog (Tools -> Code Snippets Manager)
- Open the Snippet using File -> Open File and open the file:
C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\NetFX30\propdp.snippet
- Edit the declarations (like):
<Literal>
<ID>name</ID>
<ToolTip>Event Name</ToolTip>
<Default>MyEvent</Default>
</Literal>
- Edit the snippet using $name$ for any literal replacement.
- Be sure to change the shortcut in the XML to "revent".
- Save the file as "revent.snippet"
- Your visual studio instance should now see the snippet.
Here is the snippet code I used:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Define a RoutedEvent</Title>
<Shortcut>revent</Shortcut>
<Description>Code snippet for a event using RoutedEvent</Description>
<Author>Nathan Zaugg</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>eventhandlertype</ID>
<ToolTip>Event Handler Type Type</ToolTip>
<Default>RoutedEventHandler</Default>
</Literal>
<Literal>
<ID>name</ID>
<ToolTip>Event Name</ToolTip>
<Default>MyEvent</Default>
</Literal>
<Literal>
<ID>ownerclass</ID>
<ToolTip>The owning class of this Property.
Typically the class that it is declared in.</ToolTip>
<Default>ownerclass</Default>
</Literal>
<Literal>
<ID>routingstratigy</ID>
<ToolTip>The routing stratigy for this event.</ToolTip>
<Default>Bubble</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[
// Provide CLR accessors for the event
public event RoutedEventHandler $name$
{
add { AddHandler($name$Event, value); }
remove { RemoveHandler($name$Event, value); }
}
// Using a RoutedEvent
public static readonly RoutedEvent $name$Event = EventManager.RegisterRoutedEvent(
"$name$", RoutingStrategy.$routingstratigy$, typeof($eventhandlertype$), typeof($ownerclass$));
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
When you are done it should look like this:
If you don't want to bother writing it yourself, you may download my routed event snippet here. I plan to create a code snippet for Dependency Properties that have coercion, event changed notification, and validation methods implemented so they may be overridden in descendent classes.
Links:
Silverlight 2 has been released and boasts many new features. Silverlight is a cross-platform RIA (Rich Internet Applications) platform designed to enhance the web experience. Silverlight allows developers to use a familiar set of tools and technologies to deploy functionality via the web. Silverlight also has the best capabilities for delivering video over the web including support for VC1 (HD Format) over the web and DRM (Digital Rights Management) for delivering copyrighted content over the web. Another great advantage is it's Isolated Storage which could allow things like client-side resizing of images, etc.
Some of the enhancements from previous versions includes an Embedded CLR with full 3.5 functionality and a Base Class Library, Rich UI framework (styles, animation, layout, data binding, skinning, etc.), new controls, Networking support (including WS/SOAP, REST, POX, RSS, HTTP, and sockets), and Rich Media Support for Videos, Images, Isolated Storage, etc.
Most of what I really wanted in Silverlight made it into the release so that makes me happy. I haven't seen if my plea to implement all of the data binding features WPF has was granted so I'll write a post when I find out.
Will you be using Silverlight over Flash in an upcoming project? Let me know about it!
Light Up The Web With Silverlight!
Links:
Over the summer I was lucky enough to get my home office re-done. I don't really have any before pictures but you can see it's quite nice now. I like being able to use my nice, fast computer for work! I like that I have dual monitors, software, and a good chair! Sometimes the simple things can make the work place a lot more comfortable and that has a tremendous affect on my output as a programmer. If I am not comfortable I don't work as fast! The irony is that I am writing this while at work in a cold, noisy, dusty warehouse! I suppose the sad part of that irony is that I'll probably never get a real office nearly as nice as my home office. Hopefully I'll be able to work from home sometime in the future!
Pictures
Image 1: Office Entrance. Oh, I love my dual flat panel monitors. My computer is also pretty flashy. I'll post specs below.
Image 2: Guest Desk. This is place where a friend can come over and have a space to work. This office chair is pretty cheap though -- It doesn't recline!
Image 3: Office Sofa! This is nice when it's late at night and I am waiting for a query to return or an import to run, etc.
Image 4: Storage & Mountain Dew for Phil when he comes over to work.
Product Reviews
I got those cabinets from Ikea and it is very much a love/hate type of thing. They weren't too expensive as far as shelving but I'm still not convinced of their value. I had to drill a hole in the side to get some cables into the cabinet for printers and such and got to see what was inside. Most people at this point say "Oh no, not particle board!" and I usually laugh. Here is what it is really made of:
- Laminate (no surprise)
- 1/8" particle board
- Corrugated Paper & Glue
- 1/8" particle board
- Laminate (even on back surfaces -- it's load bearing laminate)
To my surprise it is more sturdy than it sounds and very light! The limitation is that it's vulnerable to squeezing. You can actually squeeze the wood (including the desk) with your bare hands. I think that the shelves will wear just fine, but I am skeptical if the desk is going to stand up to any wear.
My other gripe about the cabinets is that they weren't very easy to hang. They are meant to hang from a wall like this but the screws and brackets are woefully inadequate and the holes provided are not on 16" centers so you can never hit more than 1 stud.
I got the sofa from Ashley Furniture and I LOVE IT! It's extremely comfortable and was inexpensive. The cushions do not come out so it's nice not to have to worry about pushing them back in before sitting down. I plan on getting new & bigger whiteboard and some artwork and I can call it complete!
Computer Specs
My computer is about 18 months old. It's a Dual Core AMD64 with 2GB RAM (soon 4GB) running Windows Vista Ultimate. I have a RAID 1 array for speed (makes the biggest difference in speed than anything else) and dual flat panel monitors. The monitors were purchased a few years ago and so they have a relatively low resolution of 1280x1024, but they are the same exact model in with consecutive serial numbers so the colors match exactly! I also have a USB TV/Video capture device. I use this device with Windows Media Center to record HDTV. My XBOX 360 can then connect to my computer as a Media Center Extender and play the recorded shows. It works pretty good though I need to get up in the attic and adjust my HD antenna. I also have a 2GB Thumb Drive that runs ReadyBoost for better prefetch performance (makes things go fast)! I hope to upgrade the core to a quad-core AMD when I get some extra money, but it's still the fastest computer I've used.
Silverlight 2 is not far from reality! With the first RC coming just months after the beta 2 release and promises of a full release coming soon we can start migrating existing beta 2 code to RC0 which is supposed to be compatible with the actual release. The announcement is posted on Scott Gu's blog here. I am excited to read that some of the major changes are making WPF and Silverlight. Also, they have promised a bunch of new controls which will make Silverlight more control rich than WPF (with some exception).
My computer is still messed up from the Beta 2 release so I'm hoping that installing the RC0 release will fix some things up -- I'll post on that later.
Another six months have come and gone and it's time for another Utah Code Camp! I can't believe how quickly this sneaks up on me every time! For those in the area Code Camp is a high quality, free training event! The topics range greatly from Microsoft, Java, Ruby, XBOX & Wii Development, Agile, Project Management, etc.. These presentations are by developers for developers and allows you to catch up on the sea of new technology that continually floods us. More on the Code Camp Manifesto can be found here.
Before I share the details I would appreciate any feedback on a good topic to present. I haven't replied with a topic yet and I'll need to get one soon so I can get started on the presentation. Previously I have presented on .NET 3.5 / VS 2008, WPF, and Silverlight 2. A big topic in MSDN magazine these days seems to be parrallism, but that topic feels rather dry to me. Other ideas I have had were LINQ in Depth, DSL Tools, F# (though I hope someone else does this one), or WPF for Newbs.
Here are the specifics:
When: Saturday November 1, 2008
Where: Neumont University, Building 2, 2nd Floor (directions)
We are also always looking for sponsors. It takes a lot to put on this event and contributions help a lot! For more information about sponsorship, please visit http://www.utcodecamp.com
Links:
I subscribe to Redmond Press "Redmond Report" which is something of a news channel for Microsoft. The editor was asking for peoples reviews of Chrome so they could do a composite review. Having recently done a post about chrome on my blog I wrote the day it came out I decided to send him the URL as my Reader Review. I was surprised last week when the headliner of that edition featured my (this) site.
The full article is here, but here is what it said:
Shiny, Happy Chrome Site
One reader gets down to the nitty gritty with Chrome. Plus, clickjacking makes its presence known, details on the next rev of Visual Studio released, and more.
September 30, 2008 • by Doug Barney
Reader Nate sent me an e-mail last week about his online review of Chrome. The review was so well-done and so well-written, I thought I'd give good, old Nate a plug.
What Nate did is similar to what I'm doing with an upcoming Reader Review -- getting the skinny on Chrome. In Nate's case, we see one very well-informed opinion backed by his benchmarks. In my story, over a dozen Redmond Report readers will help form an overall evaluation of Chrome.
Here's what Nate liked: the sparse interface, speed and private browsing (what are you trying to hide, Nate?). On his not-so-good list? No advances in bookmarking and a processor-intensive architecture.
In addition to that I also received some very good comments about the post. Personally, I didn't feel like this was one of my better posts but I'm glad that it was found to be informational to some.
Links:
WPF has built-in controls for ink, but is missing much of the API that is available in the TabletPC SDK 1.7. As a result, unless you are doing the most basic and mundane ink you will be required to use this library. One of those basic things that are missing is the ability to open the TextInputPanel in an WPF application.
The TextInputPanel is a tool that ships with certain versions of Vista (in previous versions of windows it was called a Pen Input Panel) that enables handwriting recognition and an on-screen keyboard. It makes text input into a text box easy when the user is operating with a Tablet PC. The problem is that the .NET assembly only supports hwnd-based controls and WPF controls (thankfully) are not hwnd-based.
So while trying to figure this out, and off the clock from the project I was on, I made a class that helped bridge the gap between WPF and the TextInputPanel.
Before you try to use this you will need to do two things.
First you need to download and install the TabletPC SDK 1.7 (if you haven't already) and download my class (Source / Binary)
Second you need to start the Tablet PC Input Panel if you on a regular PC. To do this go to:
Start -> All Programs -> Accessories -> Tablet PC -> Tablet PC Input Panel
To use the class as a binary application, simply add the DLL as a reference. Once that is done you will need to create an instance of the class for each text box you wish to have ink input (shown below). IMPORTANT: THIS SHOULD BE DONE ON THE WINDOW LOAD EVENT! IF YOU PUT THIS CODE IN THE CONSTRUCTOR IT WILL NOT WORK!
<?xml version="1.0" encoding="utf-8"?>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestApp"
Title="Ink Input App"
Loaded="Window_Loaded">
<Grid>
<TextBox Name="tbTest" Height="30" Width="300" />
</Grid>
protected InkInputPanel pnltbTestInk;
...
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Enable the Ink Input Panel
pnltbTestInk= new InkInputPanel(tbTest, true);
}
The code above will display the TextInputPanel anytime the textbox has focus and will go away when it looses focus. This is the simplest way to use the class. If you are doing something more complex like making the input panel appear when a button is clicked you will have some slightly different code.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Enable the Ink Input Panel
pnltbTestInk = new InkInputPanel(tbTest, false); // False for AutoShow
}
private void InputFieldButton_Click(object sender, RoutedEventArgs e) {
tbTest.Focus();
pnltbTestInk.Show();
}
protected void tbTest_LostFocus(object sender, RoutedEventArgs e) {
pnltbTestInk.Hide();
}
Just make sure that you focus the text box before you call show on the Text Input Panel.
Basically the class I created uses the COM object exposed by the SDK rather than the Microsoft.Ink.dll assembly. The COM object is called "Microsoft PenInputPanel 1.7" and is found at C:\Program Files\Common Files\Microsoft Shared\ink\tiptsf.dll
If you are able to make use of my class or have questions or feedback, please leave a comment!
UPDATE
I received a number of emails indicating that using this code for multiple text boxes didn't work (it threw a COM exception). I have modified the code to fix this issue and have uploaded it. Because of a COM limitation, there is a change in how you use the API. The biggest change is that you only need one instance of the class and you can attach multiple text boxes to this one instance.
Example:
protected InkInputPanel pnltbTest;
...
private void Window_Loaded(object sender, RoutedEventArgs e) {
pnltbTest = new InkInputPanel(tbTest, true);
pnltbTest.AddAttachedTextBox(tbTest1, true);
pnltbTest.AddAttachedTextBox(tbTest2, true);
pnltbTest.AddAttachedTextBox(tbTest3, true);
}
if you are going to hide and show the panel explictly, then you will need to use one of the indexers available on the InkInputPanel class.
Example:
protected InkInputPanel pnltbTestInk;
...
private void Window_Loaded(object sender, RoutedEventArgs e) {
// Enable the Ink Input Panel
// Pass false for AutoShow
pnltbTestInk = new InkInputPanel(tbTest, false);
}
private void InputFieldButton_Click(object sender, RoutedEventArgs e) {
tbTest.Focus();
pnltbTestInk[tbTest].Show();
}
protected void tbTest_LostFocus(object sender, RoutedEventArgs e) {
pnltbTestInk[tbTest].Hide();
}
Links