Metro Theme Resources and Templates

Posted Thursday, April 26, 2012 by

One thing that always helps when building xaml applications is to have easy access to reference the Theme resources and control Templates.

Thankfully for building Windows 8 Metro style applications you can find the appropriate files at C:\Program Files\Windows Kits\8.0\Include\winrt\xaml\design.

ThemeResources.xaml contains the resource dictionaries for the Dark (Default), Light and HighContrast themes while Generic.xaml contains the default styles and templates for most of the xaml controls. Incredibly useful when needing to know how the control is put together and how you can affect it.

For instance FlipView has a 3 pixel margin built into it, which is nice to know before trying to track down why your alignment is a little in your own code.

I'm spending a lot of time with Windows 8 at the moment so will be blogging about it more here or a the Marker Metro website.

Extending the ListBox control

Posted Saturday, May 21, 2011 by

I'm currently going through a process of bringing together code and controls I've been using in the last few applications and compiling my own "toolkit". The idea will be a very opinionated way of building WP7 applications rather than a generic control library. Some parts will be controls like the "empty list box" discussed in this post and other parts will be extensions to the Caliburn.Micro MVVM framework for how I like to work.

The first control is an extension of the ListBox control to display certain content when there are no items in the list. It's a simple extension but most of the time we forget to add this functionality especially when we're dealing with lots of lists in our application.

The first thing we'll do is create our class ListBox (not the best name, but no other one like EmptyListBox suites, thankfully we have namespaces for conflicting names) obviously inheriting from the system ListBox, we'll had two dependency properties, EmptyContent and EmptyContentTemplate. This will allow two different ways of defining the content to display, much like Button or ContentControl.

public static readonly DependencyProperty EmptyContentTemplateProperty =

    DependencyProperty.Register("EmptyContentTemplate", typeof(DataTemplate), typeof(ListBox), null);

 

public static readonly DependencyProperty EmptyContentProperty =

    DependencyProperty.Register("EmptyContent", typeof(object), typeof(ListBox), null);

 

public ListBox()

{

    DefaultStyleKey = typeof(ListBox);

}

 

 

public object EmptyContent

{

    get

    {

        return GetValue(EmptyContentProperty);

    }

    set

    {

        SetValue(EmptyContentProperty, value);

    }

}

 

public DataTemplate EmptyContentTemplate

{

    get

    {

        return (DataTemplate)GetValue(EmptyContentTemplateProperty);

    }

    set

    {

        SetValue(EmptyContentTemplateProperty, value);

    }

}

Our default Style in Generic.xaml will be pretty simple.

<Style TargetType="controls:ListBox">

    <Setter Property="Background" Value="Transparent"/>

    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>

    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>

    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>

    <Setter Property="BorderThickness" Value="0"/>

    <Setter Property="BorderBrush" Value="Transparent"/>

    <Setter Property="Padding" Value="0"/>

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="controls:ListBox">

                <Grid>

                    <ContentPresenter x:Name="EmptyContent" Content="{TemplateBinding EmptyContent}" ContentTemplate="{TemplateBinding EmptyContentTemplate}" RenderTransformOrigin="0.5,0.5" >

                        <ContentPresenter.RenderTransform>

                            <CompositeTransform/>

                        </ContentPresenter.RenderTransform>

                    </ContentPresenter>

                    <ScrollViewer x:Name="ScrollViewer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}">

                        <ItemsPresenter/>

                    </ScrollViewer>

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>

We'll then override the OnItemsChanged to add our new behaviour when items are added or removed.

There are a few different ways we can implement the required functionality each with their own pros and cons.

Using Control Template Parts

The first is using Template Parts, this allows controls to tell developers which sub-controls they expect in the control template. The can then interact with them using the FindTemplateChild method. The ListBox control already defines a ScrollViewer as a part, we would then add a ContentPresenter as a second part. In our overriden method we could then set the Visibility of each control appropriately. This approach is the simplest and the code is as follows.

private ContentControl emptyContent;

private ScrollViewer scrollViewer;

 

public override void OnApplyTemplate()

{

    base.OnApplyTemplate();

 

    emptyContent = (ContentControl)GetTemplateChild("EmptyContent");

    scrollViewer = (ScrollViewer)GetTemplateChild("ScrollViewer");

}

 

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

{

    base.OnItemsChanged(e);

 

    ApplyTemplate();

 

    var hasItems = Items.Count > 0;

 

    emptyContent.Visibility = hasItems ? Visibility.Collapsed : Visibility.Visible;

    scrollViewer.Visibility = hasItems ? Visibility.Visible : Visibility.Collapsed;

}

Using Visual States

The second approach is to use the VisualStateManager to hide and show parts of our control template. I like this approach better as it gives better flexibility to developers extending the control. By defining two states "Empty" and "NonEmpty" we put it back in the developers hands about how each state should look, rather than arbitrarily defining the behavior ourselves. This approach makes the control code itself simpler than the first but we have more xaml in the Control Template due to having to define the new states.

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

{

    base.OnItemsChanged(e);

 

    ApplyTemplate();

 

    VisualStateManager.GoToState(this, Items.Count > 0 ? "NonEmpty" : "Empty", true);

}

The xaml for the Visual States is pretty long so I won't post it here but it will be available in the download available soon.

Over all I prefer the second approach due it's freedom and the ability to add animations. The default template has a simple "continuum" animation bringing the content into view.

Download the source.

Creating a delete animation using Expression Blend

Posted Wednesday, April 27, 2011 by

The email app on Windows Phone 7 has slick delete animation whenever you delete a single email, the whole page shrinks in size and then falls of the bottom of the page, once I'd seen it I knew I wanted to bring a similar animation to To Do Today. Here's how I created it in Blend.

While the UI for Blend is great for laying up my pages on the phone it's a little difficult to work with animations using the default layout. Thankfully Blend has the concept of Workspaces, if you go to the Window / Workspaces menu and select Animation Blend will rearrange the user interface to better deal with things like timelines.

The first thing we do create the storyboard, under the storyboard section select the New button and then give the storyboard a name, I'm calling mine AnimateDelete (original I know).

Once the storyboard is created Blend is in record mode, anything we do to our page is recorded as part of the storyboard.

To animate the entire page we'll be manipulating the element LayoutRoot, so locate that in the Objects tree. The first step is to create a keyframe on the timeline about half a second in, this will be the frame where we've finished shrinking the page and start the drop. Move the timeline marker out to half a second into the timeline and hit the record keyframe button.

With that keyframe selected set the Scale transform to 0.5 to halve the size of the page. We then create the keyframe to tell the animation when to stop the drop. At around a second into the timeline create a second keyframe and with that selected set the Translate Y transform to 600.

To make the animations feel a little more fluid lets set some easing functions to both keyframes. Select each keyframe and in the properties panel set the easing function to ExponentialInOut with an exponent of 6.

You can preview the animation using the timeline and tweak the values to suit your own taste.

Now lets plug the animation into the page, I have an event handler for the delete button on the application bar, we'll use the method I created in a previous blog post to call the Delete method on the view model when the animation is complete. If we didn't do this then our business logic would complete so quickly we wouldn't see the animation.

private void OnDeleteAll(object sender, EventArgs e)

{

    AnimateDelete.Begin(ViewModel.DeleteAll);

}

Hope this helps some people get an idea how easy adding animation to your apps can be.

Executing code on animation completion

Posted Monday, March 21, 2011 by

The eventing mechanisms in .NET are great for being notified when certain things occur, but often you don't care about every occurrence just the next one, really what you're wanting is a callback. The most common scenario I've encountered for this during my development on the Windows Phone 7 is wanting to execute code after an animation is complete and by extension when an animation part of a visual state is complete.

What I want to show is two different mechanisms to create one time event handlers, then how to build simple extension methods to make use of these to create callbacks and then also how to use it with animations and the visual state manager.

The first and easiest method is a self removing event handler, rather than simply adding an event handler to the event we first create the event handler as a separate variable initialised as null. We then initialise the handler as a lambda that does what you need to do and then takes advantage of closures to remove itself from the event.

This can seem quite complicated, what makes this work is that we're splitting what would usually be one statement (declaring the event handler and assigning to the event) into three, declaring the reference to the handler, declaring the handler itself and assigning to the event. By splitting the declaration of the variable and the initialisation means we can reference the variable in the handler itself.

public void AttachWithHandler()

{

    EventHandler handler = null;

 

    handler = (s, e) =>

    {

        MessageBox.Show("Completed!");

 

        storyboard.Completed -= handler;

    };

 

    storyboard.Completed += handler;

}

The alternate way is to use the new library from Microsoft called Reactive Extensions this allows us to use a more declarative syntax, for one off event handlers the important method is the Take(1). What's cool about this approach is that you can handle multiple events easily over the first approach. We can also add filters and other features of the Reactive Extensions framework to our handler if required.

public void AttachWithRx()

{

    Observable.FromEvent((EventHandler<EventArgs> e) => new EventHandler(e),

        e => storyboard.Completed += e,

        e => storyboard.Completed -= e)

        .Take(1)

        .Subscribe(e => MessageBox.Show("Completed"));

}

So now we have our approaches lets build some extension methods to make this into a simple extension method, rather than caring about a full event handler all we really want is to be able to define a callback method and have that executed on event completion. To solve our storyboard completion animation problem we'll create an extension for storyboard that takes a callback and then uses the first approach to use it as a one off event handler.

public static void Begin(this Storyboard storyboard, Action callback)

{

    EventHandler handler = null;

 

    handler = (s, e) =>

    {

        callback();

        storyboard.Completed -= handler;

    };

 

    storyboard.Completed += handler;

 

    storyboard.Begin();

}

Here's how I'm using it in To Do Today.

private void OnDeleteAll(object sender, EventArgs e)

{

    AnimateDelete.Begin(ViewModel.DeleteAll);

}

Windows Phone 7 Status Indicator Control

Posted Monday, February 21, 2011 by

A lot of the built in applications have really subtle transitions and effects that really add polish to an existing application. In the process of building a new application I've been working on mimicking those controls. The first I'm releasing is the Status Indicator most commonly seen in the email application.

It's a fairly simple control that has two properties Text and InProgress controlling both the displayed status and whether the progress bar should be displayed. The control exposes two methods Display and Clear to easily set the properties of the control as well as manage state for nice animated transitions between the two.

<controls:StatusIndicator x:Name="Status" />

private void OnDisplay(object sender, RoutedEventArgs e)

{

    Status.Display("Loading...", true);

}

 

private void OnClear(object sender, RoutedEventArgs e)

{

    Status.Clear();

}

One thing that frustrates me when dealing some out of the box controls is that there's often no nice way to interact with the control when using some sort of UI separation pattern such as MVVM. To deal with this the control exposes a Source property, you can then have a property on your view model that implements the IStatusSource interface and will allow you to determine the properties and state of the control from your view model. It's all very unit testable as well!

<controls:StatusIndicator Source="{Binding Status}" />

public class StatusViewModel

{

    public StatusViewModel()

    {

        Status = new StatusSource();

    }

 

    public IStatusSource Status

    {

        get; set;

    }

 

    public void Display()

    {

        Status.Display("Updating", true);

    }

 

    public void Finish()

    {

        Status.Display(String.Format("Updated {0:d}", DateTime.Now), false);

    }

}

Of course here's the source code.

Page 1 of 41234>

Professional Windows App Development