Thursday, January 24, 2013

A few helpful TDD links

A few months ago, I had an interesting discussion about TDD with a colleague. When I returned to my desk I quickly sent him a list of links that I thought he’d find useful.

Today, I found it while cleaning up my email. I think you might find it useful, too.

I came across Miško Hevery’s blog through the Google Testing Blog.

A few of my posts that you might enjoy:

Wednesday, January 09, 2013

Windows Xaml–Triggerless

I was surprised to learn that Xaml for Windows Store applications does not have support for Triggers. Triggers within WPF (DataTriggers, EventTriggers) are a simple way to introduce interactivity to a user control such as changing the display properties when an event or data condition is satisfied. Since Triggers are declared using Xaml syntax, functional behavior can be introduced by modifying a style rather than writing code in the code-behind.

In recent years however, WPF has introduced the Visual State Manager (VSM) concept, which originally grew out of the SilverLight and WPF Toolkits before being rolled into .NET 4.0. The Visual State Manager is much easier to use because it groups previously unrelated triggers into more meaningful semantic states (MouseOver, Pressed, Normal, Disabled, etc). Triggers have played a less important role in WPF development since this time, but there were still occasions where a Data or Event Trigger made sense.

Unfortunately, triggers were not included in Xaml for Window Store applications. (Technically, EventTrigger is included but it only supports the FrameworkElement.Loaded event). So where does this leave us?

Here’s a few options:

Personally, I’m a fan of the expression Blend Behaviors, especially the InvokeCommandAction which is immensely useful when building MVVM applications. I’ll post more about these with some examples soon.

Until then, happy coding.

Tuesday, January 08, 2013

Visibility Hidden Behavior for WinRT

In my last post, I lamented the loss of the Hidden in the Windows.UI.Xaml.Visibility enumeration. Here’s an ultra-simple attached property that simulates Hidden by changing the opacity and hit testability of the element:

using Windows.UI.Xaml;

namespace Blog.VisibilityHiddenDemo
{
    public class VisibilityHiddenBehavior : DependencyObject
    {
        public static readonly DependencyProperty IsVisibleProperty = 
            DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(VisibilityHiddenBehavior),
                new PropertyMetadata(true, OnIsVisibleChanged));

        public static bool GetIsVisible(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsVisibleProperty);
        }

        public static void SetIsVisible(DependencyObject obj, bool value)
        {
            obj.SetValue(IsVisibleProperty, value);
        }

        private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if (element != null)
            {
                var visible = (bool)e.NewValue;
                element.Opacity = visible ? 1 : 0;
                element.IsHitTestVisible = visible;
            }
        }        
    }
}

Free as in beer.

Happy coding.

Monday, January 07, 2013

Windows Xaml - No Where to Hide

With thanks to my current project, I finally have a chance to build a Xaml based Windows Store application. On the whole, I think the platform is great but it seems like a complete reboot of the developer ecosystem. Favourite tools like Reflector and WPF Snoop don't have a home and it reminds me of the first few years when .NET first came out. It's going to take a little while for us all to fully understand the change and how to make the most of it.

For today I thought it would be fun to start a new series of posts related to all the gotchas I've discovered working with Windows.UI.Xaml. Today's gotcha, Visibility.

One of the first observations you'll find working with Xaml for Windows store applications is that it is not WPF. WPF has matured into the System.Windows namespace over the last six years. Windows.UI.Xaml is brand-new -- it looks like WPF but it has some interesting changes.

Today's change: Visibility.

Under WPF, the System.Windows.Visibility enumeration has three possible values:

Visible Display the element.
Hidden Do not display the element, but reserve space for the element in layout.
Collapsed Do not display the element, and do not reserve space for it in layout.

Visible seems straight forward enough, but the difference between Hidden and Collapsed is significant. The difference is shown using the Rectangle in this example:

<Window x:Class="Blog.VisibilityHiddenDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">

        <Rectangle Width="100" Height="100" Fill="Green" 
                   Visibility="Visible" />
        <TextBlock HorizontalAlignment="Center">Some Content</TextBlock>
        
    </StackPanel>
</Window>

When the Rectangle is Visible it appears on the screen as expected.

VisibilityHidden_Visible

When the Rectangle is Hidden it doesn't appear, but it still takes up space.

VisibilityHidden_Hidden

When the Rectangle is Collapsed it's at though it never existed.

VisibilityHidden_Collapsed

For applications that target Windows RT, Windows.UI.Xaml.Visibility has only two possible values:

Visible Display the element.
Collapsed Do not display the element, and do not reserve space for it in layout.

It makes we wonder why the folks at Microsoft decided to drop "Hidden" from the API. Ultimately, someone lost the debate and now we're left with an enumeration that is familiar to developers but is even more awkward that the original. Strange indeed.

So what does it mean that we have no Hidden? In the majority of cases, toggling between Visible and Collapsed is exactly what you want. But occasionally, you do want to remove something from the UI without changing the layout. For example, showing a button on the screen only when required.

So we don't have Hidden in Windows.UI.Xaml. Here's a few alternatives:

Opacity / IsHitTestVisible

One alternative to Hidden is to change the element’s opacity to zero thereby making it transparent. But beware, transparent objects are still present on the screen and can be interacted with, so if you’re hiding an interactive element such as a button, you’ll also want to set the IsHitTestVisible property to False.

Alternate Layouts

Rather than relying on the Hidden to preserve layout, another alternative is to use a different layout. Here are a few hacks that I’ve used:

Canvas Control

You can use a Canvas control and set the Canvas.Left and Canvas.Top attached properties on the children controls to position the controls exactly where you want. This seems a little heavy-handed and might only work if the content has a fixed size.

Relative positioning using Margins

The Grid control has a simple, dirty hack: if you don’t specify the Grid.Row or Grid.Column attached properties the element will default to the first column and row. You can achieve a form of relative positioning by putting multiple controls in the first position and then use margins to offset their position.

<Grid>
   <Button Width="50" Visibility="Hidden">
      <Image Source="/images/back.png" />
   </Button>
   <TextBlock Margin="55,0,0,0"
              Text="Text offset by margin" />
</Grid>

Grid-based layout

Another approach to preserving layout when Hidden is to explicitly define the layout. Again, heavy-handed if all you need is collapsed visibility.

<Grid>
   <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50" />
        <ColumnDefinition />
   </Grid.ColumnDefinitions>

   <Button Grid.Column="0" Visibility="Hidden">
     <Image Source="/images/back.png" />
   </Button>

   <TextBlock Grid.Column="1"
        Text="Text in 2nd column" />
</Grid>

Well, that’s all for now. I’ll continue to post finds on Windows 8 Xaml under the WinRT hash tag.

Happy coding!