Damian's Blog .NET from Geneva, Switzerland

24Sep/110

Evernote 2.0 for Windows Phone 7.5 (Mango) released

Filed under: Evernote, WP7 No Comments
23Sep/111

Presentation at the Evernote Trunk Conference on developing the Evernote Windows Phone client

Filed under: Evernote, WP7 1 Comment
2Aug/112

Elephants love mangoes – a look behind our Windows Phone 7 client

I wrote this article for the Evernote Tech Blog last month, summarizing my experience developing the Windows Phone Evernote client: http://blog.evernote.com/tech/2011/06/28/look-behind-evernote-wp7/

Filed under: WP7 2 Comments
30May/110

HTC Gingerbread–automatically switching from Wifi to costly data connection

I have an HTC Incredible S, and it’s a very nice phone indeed.

I recently upgraded Android 2.3.3 (Gingerbread), and discovered that the Wifi connection was dropping in places at home where it had a perfectly usable (albeit weak) Wifi signal.  Places where previously it had worked.

I fiddled with my Wifi base station, repositioning it, to no avail.

Finally I googled and found that HTC had decided to switch from Wifi to data if the Wifi signal dropped below a certain strength (88dbm).  How nice of them to decide on my behalf that I wanted to switch from my (free) Wifi to my (expensive) data plan, even though I still had a perfectly usable (and free) Wifi connection – one that worked perfectly well in the previous OS version.

This is annoying for a couple of reasons.  Firstly I can now run up horrendous data plan charges even though I’m within range of my Wifi.  Secondly, I have services I run on my local Wifi (IP Cams, remote control software) that can no longer connect when I’m off my Wifi.

I’ve been a big HTC fan for a long time, and have gone through many of their ‘phones.  This is a big disappointment for me – it stinks of paternalism/arrogance – deciding what is best for me without giving me a chance to override it.  I am sure that it isn’t arrogance/paternalism – I am sure it made perfectly good engineering sense, perhaps because less battery will be consumed on data than on Wifi when on a weak link, but give me a choice.

I contacted HTC support and was told that yes, this behavior is new and that no, there was no way to downgrade – the suggestion was to switch off the Data connection when I was at home. Right, as if I will remember to do that.

I’ve ended up installing Tasker, and setting up a rule to switch off my Data connection when within range of my home Wifi.  Not ideal, but it works.

Filed under: Uncategorized No Comments
26May/119

How to: Windows 7 incoming VPN from Android

A couple of weeks ago I tried to get my HTC Incredible S, running Gingerbread to connect via VPN to my Windows 7 box.  I failed, but today I succeeded.  This is how.

I created the incoming VPN on Windows 7 by following instructions I found on the web:

Open the Network and Sharing Center

image

Click on Change Adapter Settings

image

Press Alt-F, and select New Incoming Connection

image

Configure the incoming connection

imageimageimage

Change the IPV4 properties to specify a DHCP range

Make sure the range you specify is on your LAN, and out of the range served by your DHCP server (you can updated your DHCP server to exclude this range).

image

Check the firewall

I went to Advanced Settings under Windows Firewall, clicked on Inbound Rules, clicked on the Local Port column to sort by that column, and then verified that the line for port 1723 was set up and enabled (Routing and Remote Access (PPTP-In).

image

Set up port forwarding

I then went to my Router configuration, and set up port forwarding, so that external connections to port 1723 were forwarded to the machine I just configured (which is always allocated the same IP address by the router):

image

Now my Android device can connect to my internal VPN using the default settings.  You’ll need to know your external IP address.  You can find it using tools like http://www.whatismyip.com/ but it may change.  I have mine set up using http://www.dyndns.com/

Filed under: Android 9 Comments
11Apr/110

GoBackAction–a Windows Phone Behavior to navigate back

Behaviors are a great way to encapsulate functionality that can be used in a drag-and-drop environment such as Expression Blend.

Out of the box you get a NavigateToPageAction, but I couldn’t see an easy way to navigate backwards to the previous page using any of the built-in behaviors.  I wanted to let the user click on an item in a list, and then have the Phone automatically navigate to the previous page.

So here it is, the world’s simplest behavior:

[DefaultTrigger(typeof (ButtonBase), typeof (System.Windows.Interactivity.EventTrigger), "Click")]
[DefaultTrigger(typeof (UIElement), typeof (System.Windows.Interactivity.EventTrigger), "MouseLeftButtonDown")]
public class GoBackAction : TriggerAction<FrameworkElement>
{
    protected override void Invoke(object parameter)
    {
        var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
        if(rootFrame !=null)
        {
            rootFrame.GoBack();
        }
    }
}

Once you’ve built this class in your project, if you open your project in Expression Blend you should see the GoBackAction listed in the Behaviors section of the Assets tab.  You can then drag the behavior onto a UI element, define the event that should trigger the action, and then when the event occurs you should be automatically navigated backwards.

Filed under: WP7 No Comments
4Apr/111

Adapting Fluid List Animation to work with the LongListSelector

Colin Eberhardt at ScottLogic has been doing some excellent work showing how we can make our own UIs animate in a fluid manner similar to the built in Microsoft UIs on Windows Phone.

His Fluid List Animation is particularly neat, and I thought I’d apply it to the UI I’m developing, specifically on a couple of LongListSelectors that I embed in Pivots.

Unfortunately his code didn’t work on the LongListSelector out of the box because although Colin went out of his way to make it work with any ItemsControl, the LongListSelector is not an ItemsControl.  Fortunately his code was well commented, and it was trivial to modify it to work with the LongListSelector.

All the changes are in the OnIsPivotAnimatedChanged method in the ListAnimation class.

private static void OnIsPivotAnimatedChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
//  ItemsControl list = d as ItemsControl;
    LongListSelector list = d as LongListSelector;

Next find the section that starts with the comment “locate the stack panel that hosts the items” and replace the code that follows it (up to and including the for loop) with:

var itemsInView = list.GetItemsWithContainers(true, true);

foreach (ContentPresenter item in itemsInView)
{
    var localItem = item;
    list.Dispatcher.BeginInvoke(() =>
    {
        var animationTargets = localItem.Descendants().Where(p => GetAnimationLevel(p) > -1);
        foreach (FrameworkElement target in animationTargets)
        {
            // trigger the required animation
            GetAnimation(target, fromRight).Begin();
        }
    });
}

The key is the call to GetItemsWithContainers – the first parameter indicates we only want items that are in view, and the second indicates we want the containers (hence the ContentPresenter type in the foreach).

That’s it – Colin did all the hard work – I just adapted it – all kudos to him.

Filed under: WP7 1 Comment
25Mar/111

So you think you’ve finished implementing that new Windows Phone 7 page?

So you think you’ve finished implementing that new Windows Phone 7 page?

Have you checked that you:

  1. are using resources for all user-visible strings?
  2. have made sure the page handles rotation properly?
  3. handle the Enter key on each TextBox to move to the next TextBox, or submit the page?
  4. have set the InputScope on each TextBox?
  5. handle tombstoning properly?
  6. have set up Navigation transitions?
  7. have tested with both the Light and Dark Themes?
  8. are using the built-in resources for text styles?
  9. override the Back button press if you are displaying popups?

What have I missed?

Filed under: WP7 1 Comment
7Feb/118

Storing WP7 recorded audio as WAV format streams

The Microsoft audio recording example shows how to record audio, but it just gets a PCM encoded stream of samples – if you want to send this audio stream off somewhere else, to be played later, it needs a proper header.

Below I show you how to use a couple of methods I’ve written (WriteWavHeader and UpdateWavHeader), and I include their implementation.

Assuming you start with the Microsoft sample, when you initiate the audio recording you initialize a memory stream into which the samples will be written:

private void StartRecording()
{
    _microphone.BufferDuration = TimeSpan.FromMilliseconds(500);

    // Allocate memory to hold the audio data
    _recordingBuffer = new byte[_microphone.GetSampleSizeInBytes(_microphone.BufferDuration)];

    _recordingStream.SetLength(0);

    WriteWavHeader(_recordingStream, _microphone.SampleRate);

    _microphone.Start();
}

Note the call to WriteWavHeader to write the wav header to the start of the audio stream.

When the recording finishes, you update the header (because we need to fill in fields based on the data length):

private void StopRecording()
{
    _microphone.Stop();
    UpdateWavHeader(_recordingStream);
}

Here are the implementations of the WriteWavHeader and UpdateWavHeader methods.  The comments come from this web page describing the wav header file format.

public void WriteWavHeader(Stream stream, int sampleRate)
{
    const int bitsPerSample = 16;
    const int bytesPerSample = bitsPerSample / 8;
    var encoding = System.Text.Encoding.UTF8;

    // ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
    stream.Write(encoding.GetBytes("RIFF"), 0, 4);

    // NOTE this will be filled in later
    stream.Write(BitConverter.GetBytes(0), 0, 4);

    // Format Contains the letters "WAVE"(0x57415645 big-endian form).
    stream.Write(encoding.GetBytes("WAVE"), 0, 4);

    // Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
    stream.Write(encoding.GetBytes("fmt "), 0, 4);

    // Subchunk1Size 16 for PCM.  This is the size of therest of the Subchunk which follows this number.
    stream.Write(BitConverter.GetBytes(16), 0, 4);

    // AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
    stream.Write(BitConverter.GetBytes((short)1), 0, 2);

    // NumChannels Mono = 1, Stereo = 2, etc.
    stream.Write(BitConverter.GetBytes((short)1), 0, 2);

    // SampleRate 8000, 44100, etc.
    stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

    // ByteRate =  SampleRate * NumChannels * BitsPerSample/8
    stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);

    // BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
    stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);

    // BitsPerSample    8 bits = 8, 16 bits = 16, etc.
    stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);

    // Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
    stream.Write(encoding.GetBytes("data"), 0, 4);
    
    // NOTE to be filled in later
    stream.Write(BitConverter.GetBytes(0), 0, 4);
}

public void UpdateWavHeader(Stream stream)
{
    if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");

    var oldPos = stream.Position;

    // ChunkSize  36 + SubChunk2Size
    stream.Seek(4, SeekOrigin.Begin);
    stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);

    // Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
    stream.Seek(40, SeekOrigin.Begin);
    stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);

    stream.Seek(oldPos, SeekOrigin.Begin);
}

Filed under: WP7 8 Comments
21Jan/115

Windows Phone 7 Watermark on PasswordBox

For my textboxes I’ve been using a modified version Johan Danforth’s Watermark behaviour (binding the watermark text to a ViewModel property instead of hardcoding the text), but when I needed to do something similar for a PasswordBox I thought I was stuck.

I’ve come up with an incredibly basic, simple solution that seems to work well. Instead of just having a PasswordBox, I also have a TextBox behind it which I make invisible when the PasswordBox has content, or has focus.  Because the watermark TextBox is behind the PasswordBox, it never gets focus: it is purely visual.

Code Snippet
<Grid>
    <TextBox x:Name="PasswordWatermark" TextWrapping="Wrap" Text="{Binding Labels.password, Mode=OneTime}" Foreground="{StaticResource PhoneTextBoxReadOnlyBrush}" IsHitTestVisible="False"/>
    <PasswordBox x:Name="Password" LostFocus="PasswordLostFocus" Opacity="0" GotFocus="PasswordGotFocus" Password="{Binding Password, Mode=TwoWay}"/>
</Grid>

In the code-behind I hide/show the watermark TextBox and the PasswordBox as appropriate.  Note that I show and hide them by changing their opacity, not by setting their visibility. 

Because the PasswordBox is in front of the the watermark Textbox, when the user clicks in that area he always clicks on the PasswordBox, even if it is invisible.

Code Snippet
  1. private void PasswordLostFocus(object sender, RoutedEventArgs e)
  2. {
  3.     CheckPasswordWatermark();
  4. }
  5.  
  6. public void CheckPasswordWatermark()
  7. {
  8.     var passwordEmpty = string.IsNullOrEmpty(Password.Password);
  9.     PasswordWatermark.Opacity = passwordEmpty ? 100 : 0;
  10.     Password.Opacity = passwordEmpty ? 0 : 100;
  11. }
  12.  
  13. private void PasswordGotFocus(object sender, RoutedEventArgs e)
  14. {
  15.     PasswordWatermark.Opacity = 0;
  16.     Password.Opacity = 100;
  17. }

When populating the PasswordBox, you can call CheckPasswordWatermark() to show/hide the watermark as appropriate.

Filed under: WP7 5 Comments