Monthly Archives: August 2011

Commenting out Blocks of XAML

27
Filed under Windows Phone 7

Just happened across a very handy trick for commenting out large blocks of XAML. If you’ve worked very much with XAML, you’ve probably run into the problem of wanting to comment out a large chunk, which might or might not already have XML style comments (<!– comment here –>).

If you’ve tried it, you’ve quickly discovered you can’t nest XML comments, which isn’t so much a XAML thing as it is an XML thing.

However, there is a fairly easy solution that works quite nicely.

First, in the declaration part of your XML file (up at the very top, where all the XMLNS elements are defined), add these lines:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    ....

    xmlns:c="comment" <-- NOTICE THIS LINE
    mc:Ignorable="d c"  <-- NOTICE THE "C" in this line
    d:DesignHeight="800" d:DesignWidth="424">

And finally, when you want to add a comment, instead of the <!– –> pair as you might normally, use this instead:

<c:comment>
   I'm commenting out the use of the text block below
   
   <!-- This text block should be commented -->
   <TextBlock />

    <c:comment>This is a nested comment</c:comment>
</c:comment>

Not only can you continue to use normal XML comments as usual, but, when necessary, you can easily (and obviously) comment out entire blocks, even if they already contain other comment elements, or XML comments.

And, by using the mc:Ignorable attribute, VS and Blend complete ignore the content of the comment elements.

Not perfect, but pretty dang close!

More Fun with Generic XAML Errors

0
Filed under Troubleshooting, Windows Phone 7

Here’s another obscure XAML error I hope no one else stumbles onto.

I have several VisualStates defined for a particular UserControl. One example is:

<VisualState x:Name="Waiting">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="pnlBeforeWakeup">
            <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="0" />
        </ObjectAnimationUsingKeyFrames>

Now, I’d entered that state by hand and it worked just fine in Visual Studio, compiles and runs (at least, on the phone emulator).

But, when I tried to fire up Expression Blend, the control would load initially, but when I tried to view the States tab, crash!

After a few false starts, I just removed all my VisualStates manually and recreated one via Expression Blend.

Presto! Anyone care to guess the “fault”?

<queue Jeopardy theme>

Ok, here’s the version that works fine in both VS and Blend.

<VisualState x:Name="Waiting">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="pnlBeforeWakeup">
            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                <DiscreteObjectKeyFrame.Value>
                    <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
            </DiscreteObjectKeyFrame>
        </ObjectAnimationUsingKeyFrames>

Notice that instead of Value=”0”, Blend seems to want a specific Value element, with a Visibility sub-element.

And finally, here’s the Expression error that results from using the Value attribute as I did originally.

image

The only clues that helped were the fact that it only happened when I tried clicking on a particular State that made use of the Value=”0” for Visibility, and the mention of “StoryBoard” in the StackTrace above.

“Unspecified Error” in XAML under WP7

1
Filed under Troubleshooting, Windows Phone 7

Ran into a very strange error today that took me a bit to figure out.

Essentially, I was templating a standard ol’ Silverlight Button (I wanted it to have a bit of a gradient and a nice rounded border in this instance).

I was mainly messing around with things, so I was defining the control template inside the button control itself, instead of the more general purpose way of defining a Style.

<Button Name="btnTest" Content="Caption" Click="btnTest_Click" HorizontalAlignment="Stretch" >
    <Button.Template>
        <ControlTemplate>
                <Border BorderBrush="White" BorderThickness="3" CornerRadius="10" Margin="{StaticResource PhoneMargin}" >
                    <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FFCDCDE5" Offset="0" />
                        <GradientStop Color="#FF389940" Offset="0.25" />
                        <GradientStop Color="#FF008d00" Offset="0.314" />
                        <GradientStop Color="#FF002200" Offset="1" />
                    </LinearGradientBrush>
                </Border.Background>
                <TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="Stretch" TextAlignment="Center" FontFamily="Segoe WP" FontSize="{StaticResource PhoneFontSizeExtraLarge}" Margin="0,6,0,18"/>
            </Border>
        </ControlTemplate>
    </Button.Template>
</Button>

Nothing special, but when I ran the program and navigated onto the page containing this button….

image

Ugh, Just about the most general error message possible.

Fortunately, I’d checked things in just a little earlier so I had a record of what had changed, the main thing being that I’d added the use of the TemplateBinding Content feature.

The idea there is to be able to customize exactly what UI element is used to display the “Content” property of the Button control itself. As you can see, I set the button’s Content to “Caption” and then bind to that in a TextBlock.

Simple stuff.

But it crashed.

If I took out the TemplateBinding reference, everything worked just fine.

After a lot of headscratching, I eventually realized that in this case, I did NOT provide a TargetType argument to ControlTemplate. I guess I was thinking that sense the ControlTemplate was being defined within an actual control instance, it wasn’t necessary. Lo, I was but mistaken!

Once I’d specified the TargetType for the ControlTemplate element, everything was back on track.

<Button.Template>
    <ControlTemplate TargetType="Button">

It truly is the tiny things in XAML that’ll get you!

Determining Whether You’re Running on the Windows Phone Emulator or Not

0
Filed under .NET, Windows Phone 7

This is a tiny little quick-tip for Windows Phone 7

I came up with a tiny little function to make it easy to check whether you’re running under the Windows Phone Emulator this afternoon.

    Public Function IsEmulator() As Boolean
        Select Case Microsoft.Devices.Environment.DeviceType
            Case Microsoft.Devices.DeviceType.Device
                Return False
            Case Microsoft.Devices.DeviceType.Emulator
                Return True
            Case Else
                '---- just a fall back case
                Return True
        End Select
    End Function

It’s trivial really, I know, but I often wrap these kinds of utility functions in an easy-to-remember function name, because remembering “Microsoft.Devices.Environment.DeviceType” is a lot more difficult than “IsEmulator” <g>.

Showing a Bing Map in Windows Phone 7.1 With Directions

0
Filed under .NET, Windows Phone 7

image

For a Windows Phone 7 app I’ve been playing with, one last element I wanted to include was a “directions” function. Basically, I just wanted to pop up a Bing Map with a start and end point and directions, much like you’d get if you went directly to the maps application on the phone and manually entered the start and end point.

The API for this is pretty straightforward, at least for WP7.1 (Mango).

Essentially, you create a BingMapsDirectionsTask, supply a start and end point and invoke Show.

Dim bmt = New BingMapsDirectionsTask()
bmt.Start = New LabeledMapLocation(StartName, New GeoCoordinate)
bmt.End = New LabeledMapLocation(EndName, New GeoCoordinate)
bmt.Show()

The problem was that New GeoCoordinate element. For the BingMapsDirectionsTask, you have to supply two LabeledMapLocation objects, one for the start and one for the end point.

No big deal, but according to the docs, you need to supply a Name for the labeled location, and a coordinate (essentially, just a Lat/Lon). This means that if all you have is an address, supplying the lat/lon becomes an issue of geocoding, and as far as I can tell, there’s no built-in service on the phone to geocode addresses.

I was able to turn up several good examples of using the BingMapGeoCodeService online, and they all worked fine (once you go through the requisite step of obtaining an AppID from www.bingmapsportal.com).

But, in the process of making that work, I discovered something interesting.

When creating the LabeledMapLocation objects for the start and end points, if you supply an address for the name, and nothing  for the GeoCoordinate, the BingMapsDirectionsTask will automatically geocode the address!

The Disclaimer

I’m not sure whether this is intentional behavior, as the available docs for BingMapsDirectionsTask are pretty sparse, and it could be that this won’t make it into the final 7.1 release.

But, it sure makes interacting with BingMaps for simple direction functionality ridiculously easy.

The final code, then, would look like this:

Dim bmt = New BingMapsDirectionsTask()
bmt.Start = New LabeledMapLocation("12 Main St, Dallas, Tx 76011", Nothing)
bmt.End = New LabeledMapLocation("500 Oak Lawn Ave, Dallas, Tx, 76011", Nothing)
bmt.Show()

Granted, using the BingMapGeoCodeService, you’ll have a lot more flexibility, including the ability to specify the level of confidence at which to filter geocoding hits, and you can actually retrieve multiple hit values and present them to the user in whatever fashion you want.

Let me know how it works for you!

Helpful Enum Description Attribute

2
Filed under .NET, VB Feng Shui

imageWhen you work with Enums, often, it’s nice to have a description to go along with the value. Of course, you can use reflection to retrieve the name of the enum, and that’s sufficient for many purposes. But sometimes, using the name ends up being awkward, or just won’t work.

For those times, I created an EnumDisplayName Attribute.

First, the attribute definition:

<AttributeUsage(AttributeTargets.Field)> _
Public Class EnumDisplayNameAttribute
    Inherits Attribute

    Public Property DisplayName As String

    Public Sub New(ByVal DisplayName As String)
        Me.DisplayName = DisplayName
    End Sub
End Class

Using it would then look something like this:

Public Class Core
    Public Enum ChimeSoundsEnum
        <EnumDisplayName("None")> _
        None = 0
        <EnumDisplayName("Air Raid")> _
        AirRaid = 1
        <EnumDisplayName("Beeper")> _
        Beeper = 2

Now, all you need is an extension method on Enum to read the DisplayName for a particular enum value:

Imports System.Runtime.CompilerServices

    <Extension()> _
    Public Function DisplayName(ByVal e As [Enum]) As String
        Dim enumType = e.GetType
        If enumType.IsEnum Then
            Dim f = enumType.GetField(e.ToString())
            Dim displayNameAttribute = DirectCast(f.GetCustomAttributes(GetType(EnumDisplayNameAttribute), False).FirstOrDefault(), EnumDisplayNameAttribute)

            If displayNameAttribute IsNot Nothing Then
                Return displayNameAttribute.DisplayName
            End If
        End If
        Return [Enum].GetName(enumType, e)
    End Function

And finally, to read all the DisplayNames for a particular Enum type:

    Public Function GetEnumDisplayNames(ByVal et As Type) As String()
        If et.IsEnum Then
            Dim l = New List(Of String)
            Dim flds = From f In et.GetFields Where f.IsLiteral = True
            For Each f In flds
                Dim desc = DirectCast(f.GetValue(f), [Enum]).DisplayName()
                If Desc IsNot Nothing Then
                    l.Add(desc)
                End If
            Next
            Return l.ToArray
        Else
            Return Nothing
        End If
    End Function

Using that last function, you get back an array of DisplayNames that you can then databind to (for, say the ItemSource of a ListBox).

And finally, using these same techniques, you can create any number of other Enum metadata elements to make enums much more useful and easier to work with. You could have a ShortName attribute, a DataColumn attribute, maybe a PermissionLevel attribute, etc.

Simple No-Code Navigation in Windows Phone 7 Apps

0
Filed under Windows Phone 7

imageIn working with Windows Phone 7, one element that struck me as odd early on, is that the ApplicationBarIconButton (those “soft” buttons at the bottom of a normal WinPhone 7 page, highlighted in red in the screenshot) requires code in order to navigate. In other words, you MUST supply a CLICK event handler and in code behind, make use of the page’s NavigationService to perform the navigation.

Further, the URI to navigate to ends up in code behind as well.

Not ideal.

But there is a simple solution.

URIMapping

First, to make things really simple, you need to setup URI mapping. This allows your xaml to reference, say /Settings, and actually navigate to the URI /ui/SettingsPage.xaml?pvt=Main.

To do this, open up your App.xaml file and add something like this:

    <Application.Resources>
        <!-- URIs for navigation purposes -->
        <nav:UriMapper x:Key="UriMapper">
            <nav:UriMapping MappedUri="/ui/SettingsPage.xaml?pvt=Main" Uri="/Settings" />
        </nav:UriMapper>
    </Application.Resources>

Obviously, the MappedUri property is what you would normally use in conjunction with NavigationService.Navigate to actually perform the navigation. The Uri property is the new “simplified” Uri that you can use throughout your app to refer to the same page.

If you don’t already have it in your App.xaml file, be sure and add the namespace line for nav:

    xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone"

Create the New ApplicationBarIconNavigator control

Create a new class, call it ApplicationBarIconNavigator, and use the following code:

''' <summary>
''' Provides a handy extension to the ApplicationBarIconButton to facilitate direct navigation
''' </summary>
''' <remarks></remarks>
Public Class ApplicationBarIconNavigator
    Inherits ApplicationBarIconButton


    Public Property URI As Uri
        Get
            Return _Uri
        End Get
        Set(value As Uri)
            _Uri = value
        End Set
    End Property
    Private _Uri As Uri


    Private Sub ApplicationBarIconNavigator_Click(sender As Object, e As System.EventArgs) Handles MyBase.Click
        DirectCast(App.Current.RootVisual, PhoneApplicationFrame).Navigate(Me.URI)
    End Sub
End Class

This Class inherits from the normal ApplicationBarIconButton, but makes two critical changes.

First, it exposes a URI property, to allow us to specify what URI we want to navigate to.

Second, it automatically handles the Click event, and navigates to that URI.

This combination allows us to specify the URI to navigate to and handle the navigation event, all from XAML with no code on the page’s code behind at all.

The ApplicationBarDefinition

Now, in your page’s xaml, usually toward the end of the file is the definition of the ApplicationBar.

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBarIconButton IconUri="/Images/Settings.png" Text="Settings" Click="Settings_Click"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

Note that I’ve got only one button defined, and its Click event is set to About_Click, so normally, I’d have to navigate to the event handler, and add code there to perform the actual navigation:

    Private Sub Settings_Click(ByVal sender As Object, ByVal e As EventArgs)
        Me.NavigationService.Navigate(New Uri("/ui/SettingsPage.xaml?pvt=Main", UriKind.Relative))
    End Sub

Not a huge issue, but it does mean you’ve got code behind where there really doesn’t need to be any, which means more code to maintain, etc.

But, with the new control in place (you may have to perform a Build before you can add a reference on the page to it without error), and with the URIMappings set up, you can now do something like this:

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <local:ApplicationBarIconNavigator 
IconUri="/Images/Settings.png"
Text="Settings"
Uri="/Settings" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

At this point, you’re done! You no longer need the event handler logic because the ApplicationBarIconNavigator button will automatically handle it. And your URI complexity is isolated to just the App.xaml resources. Sweet!

One final note, if you haven’t already included one, you’ll need to add a “local” namespace declaration in your page’s xaml so that local:ApplicationBarIconNavigator will resolve.

    xmlns:local="clr-namespace:{your project name}" 

Wrapup

With MVVM frameworks like Prism, I believe this kind of functionality is baked in to some degree. But in my case, just starting out with WP7, I believe it’s important to understand the underpinnings of the system first, then progress to a higher level framework.

Comparing an Int32 to a UInt32

0
Filed under .NET, p/Invoke, RawMouse

imageI’ve been working on a little project to involves raw mouse support lately. If you haven’t ever heard of raw mouse, don’t feel too bad. It’s a pretty esoteric part of Windows that’s been around since the XP (and possibly earlier) days, but isn’t widely used.

Essentially, it’s trivially easy to plug a second mouse into your computer and just use it. The cursor onscreen reacts to both mice equally,  and usually, that’s exactly what you want.

However, what if it’s not?

What if you’re working on a game and you want to be able to see each mouse’s input independently? Windows does such a good job of hiding the mouse plumbing that doing so is impossible using standard mouse access techniques. Even DirectInput can’t do it, although you’d sure swear that a function like this:

Manager.GetDevices(DeviceClass.Pointer, EnumDevicesFlags.AttachedOnly)
shouldn’t have any problems doing so (it doesn’t work, I tried it!)

RawMouse to the Rescue

Turns out, you CAN get at multiple mice independently through the lower level mouse support functions, call the RawMouse layer. Essentially, the way it works is you register a window handle to receive RawMouse messages and then you react to those messages appropriately. But a full discussion of RawMouse will have to wait for another day.

In any case, you’ll be dealing with raw Windows Message blocks and it’s often not particularly easy for .Net languages to directly parse those blocks.

Or is it?

Comparing

At one point, I needed to compare an Int32 value (a signed 32bit integer value) to a UInt32 value (an unsigned 32 bit integer). Sounds straightforward, and often, a simple CType will work. But if the UInt32 value is greater than 2^30, it’ll overflow if you try to use CType on it (unlike C#, where a cast from UInt32 to Int32 just works, sigh).

I knew the Marshal class had all sorts of functions for doing manipulation like this, but in searching around, I was reminded of a little trick I used quite some time ago, when I was first getting into .net, and which had subsequently exited from my consciousness.

It turns out that the Imports System.Runtime.InteropServices namespace includes several attributes that control the layout of structures.

The two in particular we’re interested in is

  • <StructLayout(LayoutKind.Explicit)>
  • <FieldOffset(0)>

The StructLayout attribute is applied to the entire structure and it basically says that you the programmer will be explicitly determining the positioning of the fields (members) of the structure.

The FieldOffset atttribute, on the other hand, is applied to each field in the structure and determines where (using a 0 based offset in bytes) in the entire block of memory that defines the structure, that particular field will be located.

When you put it all together, you get a structure like this:

    <StructLayout(LayoutKind.Explicit)> _
    Public Structure UnionInt32
        <FieldOffset(0)> _
        Public Int32Value As Int32
        <FieldOffset(0)> _
        Public UInt32Value As UInt32
    End Structure

Which, when put simply, just accesses the first 4 bytes of the structure (due to the FieldOffset of both fields set to 0) as either an Int32 value or a UInt32 value.

Using it couldn’t be simpler (or faster).

Dim v as Int32 = -1234
Dim u as UnionInt32
u.Int32Value = v
debug.print u.UInt32Value

The V variable contains your starting signed value, and the debug.print outputs the equivalent unsigned value.

Using this trick can be a godsend when working directly with low level Windows messages (like the RawMouse messages!)