Author Archives: Ben

C# 4.0 How-To Available Now!

Well, it’s finally out! Amazon no longer lists the book as available for pre-sale, and it should be shipping to purchasers today or tomorrow. If you’re a B&N shopper, you can also order it there, or grab it in stores within a few days.

From the product description:

Real Solutions for C# 4.0 Programmers

Need fast, robust, efficient code solutions for Microsoft C# 4.0? This book delivers exactly what you’re looking for. You’ll find more than 200 solutions, best-practice techniques, and tested code samples for everything from classes to exceptions, networking to XML, LINQ to Silverlight. Completely up-to-date, this book fully reflects major language enhancements introduced with the new C# 4.0 and .NET 4.0. When time is of the essence, turn here first: Get answers you can trust and code you can use, right now!

Beginning with the language essentials and moving on to solving common problems using the .NET Framework, C# 4.0 How-To addresses a wide range of general programming problems and algorithms. Along the way is clear, concise coverage of a broad spectrum of C# techniques that will help developers of all levels become more proficient with C# and the most popular .NET tools.

Fast, Reliable, and Easy to Use!

  • Write more elegant, efficient, and reusable code
  • Take advantage of real-world tips and best-practices advice
  • Create more effective classes, interfaces, and types
  • Master powerful data handling techniques using collections, serialization, databases, and XML
  • Implement more effective user interfaces with both WPF and WinForms
  • Construct Web-based and media-rich applications with ASP.NET and Silverlight
  • Make the most of delegates, events, and anonymous methods
  • Leverage advanced C# features ranging from reflection to asynchronous programming
  • Harness the power of regular expressions
  • Interact effectively with Windows and underlying hardware
  • Master the best reusable patterns for designing complex programs

I’ll be doing a book giveaway at some point as well, once I get my own shipment. Stay tuned!

Get it from Amazon

Get it from Barnes and Noble

How to position windows correctly at 120 DPI in WPF

If you want to place a window at a specific place in WPF, it will work pretty much as you expect—unless your DPI is 120 (the default is 96). Here’s a sample that shows how to put it where you want.

In this case, I want to put a window just under another control, aligned to its left side.

 

CalcWindow calc = new CalcWindow();
Point point = this.PointToScreen(
    new Point(0, this.ActualHeight));
 
PresentationSource source = 
    PresentationSource.FromVisual(control);
 
double dpiX = 
    96.0 * source.CompositionTarget.TransformToDevice.M11;
double dpiY = 
    96.0 * source.CompositionTarget.TransformToDevice.M22;
 
calc.Left = point.X * 96.0 / dpiX;
calc.Top = point.Y * 96.0 / dpiY;
 
calc.Show();

The crux of this is getting the current DPI. You could use P/Invoke to call native methods to get this, but the transformation matrix contains the same information as well.

A WPF Numeric Entry Control

image When WPF first shipped, there was a noticeable lack of certain controls we’ve become used to in Win32 and WinForms: Calendar, DateTimePicker, and NumericUpDown. WPF 4 adds Calendar and DatePicker, but not anything for numeric entry.

For my solution I wanted something that behaved very similarly to the WinForms NumericUpdown control.

Some of the specifications:

  1. Allows user to set Value, MaxValue, MinValue, Increment, and LargeIncrement.
  2. Text directly entered is limited to numbers
  3. Pasted text is not intercepted, but when the control has lost focus it will be validated and reset to the previous value if necessary
  4. Two buttons, for increment and decrement
  5. Holding down the buttons with the mouse causes the number to increment continuously
  6. Up and down increment and decrement by Interval
  7. Page Up and Page Down increment and decrement by LargeInterval
  8. This version only supports integers

Creating the control

To begin, create a new WPF project and add a new User Control called NumericEntryControl. This will create a pair of .cs and .xaml files.

In the XAML file, change the <Grid> root element to be a <DockPanel>.

 

<UserControl 
    x:Class="NumericEntryDemo.NumericEntryControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d"
    xmlns:my="clr-namespace:NumericEntryDemo" Width="200" Height="26">
 
    <DockPanel>
    </DockPanel>
</UserControl>

Before we add the controls, let’s add some properties to our user control to hold the values the controls will use. These are dependency properties in order to take advantage of all the WPF goodness like data binding and animation. Let’s also add standard .Net property wrappers.

 

public partial class NumericEntryControl : UserControl
{
    public static readonly DependencyProperty ValueProperty = 
        DependencyProperty.Register("Value",
            typeof(Int32), typeof(NumericEntryControl),
            new PropertyMetadata(0));
 
    public static readonly DependencyProperty MaxValueProperty = 
        DependencyProperty.Register("MaxValue",
            typeof(Int32), typeof(NumericEntryControl),
            new PropertyMetadata(100));
 
    public static readonly DependencyProperty MinValueProperty = 
        DependencyProperty.Register("MinValue",
            typeof(Int32), typeof(NumericEntryControl),
            new PropertyMetadata(0));
 
    public static readonly DependencyProperty IncrementProperty = 
        DependencyProperty.Register("Increment", 
            typeof(Int32), typeof(NumericEntryControl),
            new PropertyMetadata(1));
 
    public static readonly DependencyProperty LargeIncrementProperty = 
        DependencyProperty.Register("LargeIncrement",
            typeof(Int32), typeof(NumericEntryControl),
            new PropertyMetadata(5));    
 
    public Int32 Value
    {
        get
        {
            return (Int32)GetValue(ValueProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }
    
    public Int32 MaxValue
    {
        get
        {
            return (Int32)GetValue(MaxValueProperty);
        }
        set
        {
            SetValue(MaxValueProperty, value);
        }
    }
    
    public Int32 MinValue
    {
        get
        {
            return (Int32)GetValue(MinValueProperty);
        }
        set
        {
            SetValue(MinValueProperty, value);
        }
    }
    
    public Int32 Increment
    {
        get
        {
            return (Int32)GetValue(IncrementProperty);
        }
        set
        {
            SetValue(IncrementProperty, value);
        }
    }
    
    public Int32 LargeIncrement
    {
        get
        {
            return (Int32)GetValue(LargeIncrementProperty);
        }
        set
        {
            SetValue(LargeIncrementProperty, value);
        }
    }
}

 

Creating an incrementing TextBox

Add a TextBox inside the <DockPanel> and bind its text to the value we created in our control:

<DockPanel d:LayoutOverrides="Width">
    <TextBox 
        x:Name="_textbox" 
        Margin="2,0" 
        Text="{Binding Value, 
            Mode=TwoWay, 
            RelativeSource={RelativeSource FindAncestor,
                AncestorLevel=1, 
                AncestorType={x:Type my:NumericEntryControl}}, 
            UpdateSourceTrigger=PropertyChanged}" 
        HorizontalAlignment="Stretch" 
        HorizontalContentAlignment="Right" 
        VerticalContentAlignment="Center" />
</DockPanel>

This will create a TextBox that sizes itself with its parent (a feature I wanted, but is not strictly necessary) and  its text will be bound to the Value in our UserControl.

Handling text input

It used to be that you pointed with a mouse and entered text with a keyboard. However, it is common now to enter text with a stylus, gestures, or some future method not invented yet. Thankfully, WPF supports generic text input handling so you don’t have to concern yourself with the specific hardware.

 

public NumericEntryControl()
{
   InitializeComponent();
 
   _textbox.PreviewTextInput += 
        new TextCompositionEventHandler(_textbox_PreviewTextInput);
}
 
void _textbox_PreviewTextInput(object sender, 
                   TextCompositionEventArgs e)
{
    if (!IsNumericInput(e.Text))
    {
        e.Handled = true;
        return;
    }
}
 
private bool IsNumericInput(string text)
{
    foreach (char c in text)
    {
        if (!char.IsDigit(c))
        {
            return false;
        }
    }
    return true;
}

This prevents anything except numbers from being entered, whether via character recognition or keyboard. It does not, however, prevent the user from pasting non-numeric text into the box. We’ll handle that later.

Validating Text input

It’s problematic to validate and correct user input as they are entering it. For example, if you set the MaxValue to 100, then every time you enter 1000, it jumps to 100, it can be jarring. It’s a similar situation with text pasted into the control. What the NumericUpDown control does is handle these sort of situations when the control loses focus.

To prepare for this, when the control gains focus, we need to save the last valid value so we have something to restore to.

When the control loses focus, we need to first verify that it is a number and if so, clip it to the bounds of our MinValue and MaxValue. If anything fails, set it back to the previous value.

 

public partial class NumericEntryControl : UserControl
{
    private int _previousValue = 0;
 
    public NumericEntryControl()
    {
        InitializeComponent();
 
        _textbox.PreviewTextInput += 
            new TextCompositionEventHandler(
                _textbox_PreviewTextInput);
        _textbox.GotFocus += 
            new RoutedEventHandler(_textbox_GotFocus);
        _textbox.LostFocus += 
            new RoutedEventHandler(_textbox_LostFocus);
    }
 
    void _textbox_GotFocus(object sender, RoutedEventArgs e)
    {
        _previousValue = Value;
    }
 
    void _textbox_LostFocus(object sender, RoutedEventArgs e)
    {
        int newValue = 0;
        if (Int32.TryParse(_textbox.Text, out newValue))
        {
            if (newValue > MaxValue)
            {
                newValue = MaxValue;
            }
            else if (newValue < MinValue)
            {
                newValue = MinValue;
            }                
        }
        else
        {
            newValue = _previousValue;
        }
        _textbox.Text = newValue.ToString();
    }
}

Handle arrow keys

Just because WPF can handle text input from a variety of sources in a hardware-agnostic way doesn’t mean we should ignore the particular strengths of the keyboard. Specifically, we should handle the up and down arrows.

 

public NumericEntryControl()
{
    ...
    _textbox.PreviewKeyDown += 
        new KeyEventHandler(_textbox_PreviewKeyDown);
}
 
void _textbox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    switch (e.Key)
    {
        case Key.Up:
            IncrementValue();
            break;
        case Key.Down:
            DecrementValue();
            break;
        case Key.PageUp:
            Value = Math.Min(Value + LargeIncrement, MaxValue);
            break;
        case Key.PageDown:
            Value = Math.Max(Value - LargeIncrement, MinValue);
            break;
        default:
            //do nothing
            break;
    }
}
 
private void IncrementValue()
{
    Value = Math.Min(Value + Increment, MaxValue);
}
 
private void DecrementValue()
{
    Value = Math.Max(Value - Increment, MinValue);
}

IncrementValue() and DecrementValue() are pulled out as their own method because they’re used in the button-handling code as well (see below).

The code so far is a perfectly usable textbox that accepts only numbers and can be incremented using the keyboard. Typically, however, we also need to support the mouse, and for that we need buttons (unless you want to do something exotic like programs like Photoshop and Lightroom do, where text boxes have support for incrementing gestures—that’s another article).

A button you can hold down

Adding buttons to increment once per click is pretty easy, but we really want to be able to hold down the buttons and have the TextBox increment. Let’s start by adding the XAML for the buttons:

 

<UserControl 
    x:Class="NumericEntryDemo.NumericEntryControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d"
    xmlns:my="clr-namespace:NumericEntryDemo" 
    Width="200" Height="26"
    >
    <DockPanel d:LayoutOverrides="Width">
        <Button x:Name="buttonDecrement" 
                DockPanel.Dock="Left"
                Content="-" 
                Width="{Binding ActualHeight, 
                    ElementName=buttonDecrement, Mode=Default}" 
                Height="{Binding ActualHeight, 
                    ElementName=_textbox, Mode=Default}"/>
        <Button x:Name="buttonIncrement" 
                DockPanel.Dock="Right" 
                Content="+" 
                Width="{Binding ActualHeight, 
                    ElementName=buttonDecrement, Mode=Default}" 
                Height="{Binding ActualHeight, 
                    ElementName=_textbox, Mode=Default}"/>
        <TextBox 
            x:Name="_textbox" 
            Margin="2,0" 
            Text="{Binding Value, 
                Mode=TwoWay, 
                RelativeSource={RelativeSource FindAncestor,
                    AncestorLevel=1, 
                    AncestorType={x:Type my:NumericEntryControl}}, 
                UpdateSourceTrigger=PropertyChanged}" 
            HorizontalAlignment="Stretch" 
            HorizontalContentAlignment="Right" 
            VerticalContentAlignment="Center" />
    </DockPanel>
</UserControl>

Note that the button Width property is  bound to its own ActualHeight property, and the Height property is bound to the TextBox’s ActualHeight. This has the effect of keeping the buttons square, the same height as the TextBox. It’s an effect I wanted, but you can easily dispose of it. With these buttons, our control finally takes shape:

image

How fast should we increment?

Before writing the code to do the incrementing as we hold the button down, it’s worth considering how fast the incrementing should occur. Ideally, we would want it to increment at about the same rate as if we were holding down the up key on the keyboard. The keyboard repeat rate is an operating system value that we can retrieve.

There are actually two values:

private static int _delayRate = 
    System.Windows.SystemParameters.KeyboardDelay;
private static int _repeatSpeed = 
    Math.Max(1, System.Windows.SystemParameters.KeyboardSpeed);

The delay rate is how long we should wait before starting the repetition, and is given in multiples of 250ms. Roughly speaking, humans can determine and control actions with lengths of time of about 200ms, so 250ms is a good value to start with. Any shorter and the repetition might start when it was not intended (say, if they just click the button instead of holding it down).

The keyboard speed is the number of times per second we should repeat—sort of. The value can be 0, so because of the way I use it below I want to sure it’s at least 1.

To allow us to hold the button down, we need to override the default mouse handling of a button which is to disable the standard LeftMouseButtonDown/Up messages. Instead, we need to handle the PreviewMouseLeftButtonDown message and its corresponding Up message.

When we handle the down message, we need to set a timer for the keyboard delay value. When we handle the timer’s tick, we need to increment (or decrement) and change the timer’s interval to the repeat speed. This repeat speed is calculated merely by dividing 1000ms (1s) by the rate per second. There may be better ways, but this gets pretty close to the rate experienced by the keyboard on my computer. Finally, when the mouse button is released we need to stop the timer. We also do a final increment, which will cover the case where the user clicks instead of holds.

We also need to capture the mouse in case the user moves it off the button—otherwise the timer will just keep incrementing forever.

Here’s the code:

 

private DispatcherTimer _timer = 
    new DispatcherTimer();
private static int _delayRate = 
    System.Windows.SystemParameters.KeyboardDelay;
private static int _repeatSpeed = 
    Math.Max(1, System.Windows.SystemParameters.KeyboardSpeed);
 
private bool _isIncrementing = false;
 
public NumericEntryControl()
{
    ...
 
    buttonIncrement.PreviewMouseLeftButtonDown += 
        new MouseButtonEventHandler(
            buttonIncrement_PreviewMouseLeftButtonDown);
    buttonIncrement.PreviewMouseLeftButtonUp += 
        new MouseButtonEventHandler(
            buttonIncrement_PreviewMouseLeftButtonUp);
 
    buttonDecrement.PreviewMouseLeftButtonDown += 
        new MouseButtonEventHandler(
            buttonDecrement_PreviewMouseLeftButtonDown);
    buttonDecrement.PreviewMouseLeftButtonUp += 
        new MouseButtonEventHandler(
            buttonDecrement_PreviewMouseLeftButtonUp);
 
    _timer.Tick += new EventHandler(_timer_Tick);
}
 
void buttonIncrement_PreviewMouseLeftButtonDown(
    object sender, MouseButtonEventArgs e)
{
    buttonIncrement.CaptureMouse();
    _timer.Interval = 
        TimeSpan.FromMilliseconds(_delayRate * 250);
    _timer.Start();
 
    _isIncrementing = true;
}
 
void buttonIncrement_PreviewMouseLeftButtonUp(
    object sender, MouseButtonEventArgs e)
{
    _timer.Stop();
    buttonIncrement.ReleaseMouseCapture();
    IncrementValue();
}
 
void buttonDecrement_PreviewMouseLeftButtonDown(
    object sender, MouseButtonEventArgs e)
{
    buttonDecrement.CaptureMouse();
    _timer.Interval = 
        TimeSpan.FromMilliseconds(_delayRate * 250);
    _timer.Start();
 
    _isIncrementing = false;
}
 
void buttonDecrement_PreviewMouseLeftButtonUp(
    object sender, MouseButtonEventArgs e)
{
    _timer.Stop();
    buttonDecrement.ReleaseMouseCapture();
    DecrementValue();
}
 
void _timer_Tick(object sender, EventArgs e)
{
    if (_isIncrementing)
    {
        IncrementValue();
    }
    else
    {
        DecrementValue();
    }
    _timer.Interval = 
        TimeSpan.FromMilliseconds(1000.0 / _repeatSpeed);
}

And voila! A NumericEntryControl that’s basic and easy-to-use for both keyboard and mouse.

Further improvements

This isn’t the last word in numeric entry controls, by any means. There are many ways to accomplish it, and this is one that worked well for me. There are a number of further enhancements you could do (and perhaps should do):

  • More validation
  • Ensure that MaxValue >= MinValue
  • Set focus to the TextBox when the control gains focus (maybe)
  • Define strokes to increment and decrement with a stylus
  • The user can change the keyboard repeat rate through Control Panel. This program could be modified to listen for updates to this value.

There’s also another, really cool feature that I will add to this in a future post.

Download full source.

Found this article helpful? Want a resource of hundreds of similar, how-to tips? I’ve written a book that covers topics like this and more in C# 4. Check out C# 4.0 How-To!

Review: The Code Book – the most entertaining book on cryptography you’ll ever read

I recently wandered into a thrift store and as is usual in these stores I headed to the book section.(I live by the maxim that you can never own too many books.) The only thing that really caught my eye was a hardcover edition of The Code Book: The Science of Secrecy from Ancient Egypt to Quantum Cryptography by Simon Singh. A quick perusal indicated it would be worth the shelf space.

However, I severely underestimated how much I would enjoy this book. I’m about half way through and find it so interesting and compelling a read that I feel I have to write about it.

The thing that really strikes me about this book is how entertaining and readable it is. I am not a big crypto or security guru, so I came to this book largely ignorant of of the topics and history.

The book is a wonderful blend of how encryption works with the history that surrounded its development. For such a seemingly-complex topic, Singh seems to have hit the perfect blend of history and instruction. Starting with the rudimentary Caesarian ciphers (basically, letter substitution) he builds up the techniques in the millenia-old one-upsmanship game between those who encipher and those who attempt to decipher. He starts with frequency analysis and history progresses he builds upon the previous techniques in explaining ever-more sophisticated attacks.

Surrounding this technical (yet still easy to understand) instruction is a fairly thorough narration of the history where these ciphers played a crucial role, from ancient Egypt, Julius Caesar, Mary Queen of Scots’ plot against Queen Elizabeth I, to legends of buried treasure protected by unbreakable ciphers, to the formidable German Enigma machine–

And let me be clear—he will teach you exactly how Enigma worked! It’s not that complicated, once you understand the principles that came before it.

Similarly, he explains how first the Polish and then the British cracked the Enigma as it evolved from the 1930’s to the end of the war, the mistakes the Germans made, and the things that, for example, the German Navy did to increase the security of it so that it became essentially unbreakable without external help (i.e., finding a codebook).

He discusses the Navajo code talkers (there is more to it than simply speaking an obscure language!), public key security, and finally quantum computing.

If you enjoy computer security topics, history, or just like to geek out, this is a great book to read.

Coincidentally, Simon Singh is also at the center of an unfortunate controversy in the UK surrounding some (I believe justified) comments he made about the British Chiropractic Association’s practices of encouraging procedures that could be considered unsafe. Rather than defend the practices with facts, they have decided to sue him for libel (the UK is infamous for having draconian libel laws that strongly favor accusers). You can learn more at his website.

You can also read a thorough explanation of the events at the Bad Astronomy blog.

Bing LEGO mosaic

bing_lego-022-EditThis is a simple project I’ve been working on during the weekends lately. It’s the Bing logo done in LEGO plates. I’ll be moving it into my office soon.

It took maybe 6 hours of work and is about 3.4ft (1m) wide.

Feel free to leave comments at flickr, or check it out at my other LEGO posting sites (there are a couple of other shots of it):

C# 4.0 How-To now available for pre-sale!

csharp_howto_ben_watson For the last year, aside from starting a great job with Bing, I’ve also been working on a book about C# 4.0 and the upcoming .Net framework. The news: it is finally available for presale! This book is not your typical C# reference. It’s designed to be an easy guide to how to accomplish specific tasks, using a problem/solution approach. Some examples:
  • How to use P/LINQ (new in .Net 4!)
  • Override Equals and implement IEquatable<T> correctly
  • Enforce coding contracts (new in .Net 4!)
  • Convert numbers to strings in arbitrary bases
  • Various ways of rounding, including “snapping” to specific intervals.
  • Dynamic discovery of WCF services
  • Make your Silverlight 3 application run out-of-the-browser
  • Speed up array access
  • Easily split work among multiple processors
  • Localize WinForms, WPF, ASP.Net, and Silverlight apps

…and hundreds of other topics, covering everything from the basics of C# to WPF, ASP.Net, interaction with the operating system, common application patterns and more. I cover all the new stuff that’s in both the C# language and the .Net 4 framework classes, as well as existing functionality.

Each topic begins with a brief description of when/where/why you would need to use the technique, followed by a brief explanation and source code.

I often just want a reference I can quickly dive into to remind me of how something is done. This book is my attempt to put in writing what I find valuable, both when I was learning C# and now when I just need to locate a sample quickly.

Over the next few months I’ll talk more about what’s in the book, and hopefully get back into blogging more programming topics.

Lots, and lots of tiles

tiles-002Over in my flickr account, I’ve posted a picture of  part of the destruction of the LEGO shuttle. I just wanted to show the amount of tiles used in the project—it was a lot, but I didn’t count. The shuttle is sadly no more, but new projects are coming…

Lots, and lots of tiles

tiles-002Over in my flickr account, I’ve posted a picture of  part of the destruction of the LEGO shuttle. I just wanted to show the amount of tiles used in the project—it was a lot, but I didn’t count. The shuttle is sadly no more, but new projects are coming…

BrickCon 2009 this weekend—get your LEGO fix in Seattle!

DSC_2043If you’re in Seattle this weekend, BrickCon 2009 is going on, and I’ll be participating for the first time, displaying my Space Shuttle model.

The convention has more space than ever this year: 35,000 square feet.

The public hours are Saturday and Sunday, 11am-3pm. It’s only $7 per person (or max of $20 per family) and you don’t want to miss the amazing models that will be there.

More Photos

_DSC4395

I finally logged back into my flickr account and uploaded some recent photos from an evening trip to Mercer Island. It was around sunset, the light was beautiful, and I had about two hours to myself to just shoot what I could.

This hand was part of many holding a chain along some docks. The sunset was truly beautiful, but it was difficult to find a decent vantage point._DSC4424, given the people at the beach and the many trees. For more photos, check out my flickr stream.