Window Phone User Group talk

Just a quick post for those who maybe reading this after listening to me at the WPUG. The post about the keyboard behaviour can be found here;
https://pauliom.wordpress.com/2010/09/05/wp7-keyboard-helper-as-a-behavior/

If you have comments about the talk feel free to let me know, thanks.

How I think Silverlight can work on desktop & phone

I recently started to consider a new User Interface for a web application. Oh yes I want to use Silverlight but it just has zero presence on mobile devices, can I justify the speed in development/maintenance vs the lack of delivery channels. Hmm, I can try. But why should I? Windows Phone 7 (Wp7) runs Silverlight, that should certainly help me shouldn’t? But no, browse to my App on a browser on Wp7 and nothing, “no plugins here”. But why? The official line is about technical details, but I doubt that. Ok it’s not the same Silverlight but come on, it’s close enough to allow a desktop target of “restrict to Wp7 set”. So if not that then what else? Let’s imagine a world where Microsoft may pay some attention to Apple’s model. What if Microsoft can make money by only allowing apps on wp7 via a market place. Sounds like biz sense. But wait a second, if I browse to a site that has the same Silverlight app on it then why buy from the market place? Solution, stop Silverlight rendering on the browser. As I started this post, this frustrates me and stops me writing Silverlight apps for the web. But there is a way around this, “Wp7 enabled Silverlight app”. Imagine this;
1. In your Out Of Browser options you specify ‘Has Windows Phone 7 version’, and you enter the market place ID of your Wp7 application
2. You compile and deploy your Silverlight app
3. User browsers to your site via a desktop browser. They get the full experience
4. User browsers to your site from Wp7, the patched version of IE spots that the Silverlight host application has the market place id of a wp7 app. So it asks the shell’s catalogue if it has this ID, no – then prompt the user to purchase it, yes – launch the app and the user gets a specific phone experience. So there you have my idea of how we could get a shared experience, sure you’re still writing 2 apps, but now;
a) the site can have a functioning presence in a mobile browser
b) the wp7 has another selling channel, everyone’s a winner

Easy way to create bootable disk/usb from iso image

Not strictly a development problem but I’ve always found it a pain to create bootable media from iso images. Today I discovered Microsoft have a very nice tool for the job, download it and follow the very simple wizard; iso-tool

Repost of Determine Light or Dark Theme with WP7 RTM

This is not my content but a repost from http://mobileworld.appamundi.com/blogs/peterfoot/archive/2010/09/17/determine-light-or-dark-theme-with-wp7-rtm.aspx , I just wanted to ensure I didn’t lose it

In the previous Beta release you had to compare the RGB values of the background brush to determine if the theme was Light (White background) or Dark (Black background). Now there is an additional resource you can query:-

Visibility v = (Visibility)Resources["PhoneLightThemeVisibility"];
 
if (v == System.Windows.Visibility.Visible)
{
    ImageBrush ib = new ImageBrush();
    Uri u = new Uri("PanoramaBack2.png", UriKind.Relative);
    ib.ImageSource = new System.Windows.Media.Imaging.BitmapImage(u);
    PanoramaControl.Background = ib;
}

Any time you use a background image you can check the PhoneLightThemeVisibility resource and switch between different versions of the image to provide the best experience with either Black or White text.

Silverlight to resize to 100% with IE8

Had a frustrating time getting a Silverlight control to take up 100% height of the browser page. First off, this is nothing really to do with Silverlight and all about the div it’s contained in. In IE7 having the div at 100% worked fine, but in IE8 it was tiny. The problem is that in IE7 a div at 100% means, ‘please take up 100% of the available height’. Whereas in IE8 it’s, ‘please take up 100% of your parent’. So a structure like

html->body->div->div[100%]->Silverlight Control
means that in IE8 its height is basically nothing. So I added 100% to the parents up to body and still no joy. Then Hannah at Clear Breeze Design pointed out that I needed to apply it to the html tag too. That did the trick. So if you have a very simple layout you could do something like;

 html * {height 100%}

Even in my code that’s too simple but the basic take-away is that you need to follow the ancestors from the Silverlight control up until you hit a height, that’s the one it will take. If you want it to be 100% then must ensure that everyone on that chain is 100% too, including body and html.

Silverlight with ASP.NET http context gotcha

Encountered an old problem at work today. A Silverlight application which talks to an svc on the same web host wasn’t correctly sharing the same session. You could see this as the httpContext was different between the web site calling the Silverlight control and the site receiveing a request from Silverlight. It’s a simple problem; when you add a refrence to a service Visual Studio will create an endpoint in the config file, something like yourmachine.yourdomain.com. However, when you test you might just use localhost. If there is a mismatch then the session will NOT be shared. I tend to pass the endpoint address from the web site in the Silverlight initParams, I find this easier than trying to post the .host by your milage may vary. NB. This is also important when hosting on a system that uses some form of https proxy as this causes the host to look like http but you need to pass https from the client, e.g. your Silverlight control.

Wp7 Application Bar, update binding helper

As you may have read I’ve been having ‘fun’ with the Application Bar. Following the really useful post by Laurent Bugnion, I’ve written the following helper that allows you to quickly manage your editable bindable controls. It’s not as simple as I hoped, I’d prefer to be able to get the helper to search for bindable properties but I’ve yet to find a nice way to achieve this – as always I welcome suggestions. Anyway hope this helps;

using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows.Data;

namespace pauliom.Helpers
{
    public class BindingHelper
    {
        private BindingHelper(){}

        private IEnumerable<BindingExpression> bindables;
        public BindingHelper(DependencyObject parent, Type type, DependencyProperty property)
        {
            bindables = GetChildsRecursive(parent).OfType<FrameworkElement>().
                Where(c => c.GetType() == type && c.GetBindingExpression(property) != null).
                Select(c => c.GetBindingExpression(property));
        }

        public void UpdateAllBindings()
        {
            if (bindables != null)
            {
                foreach (BindingExpression binding in bindables)
                {
                    binding.UpdateSource();
                }
            }
        }

        // code from 'tucod'
        IEnumerable<DependencyObject> GetChildsRecursive(DependencyObject root)
        {
            List<DependencyObject> elts = new List<DependencyObject>();
            elts.Add(root);
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
                elts.AddRange(GetChildsRecursive(VisualTreeHelper.GetChild(root, i)));

            return elts;
        }
    }
}

So to use the code you create helper per type of control and property you want to keep updated;

private BindingHelper bindingForGridTextBoxes;
void Page_Loaded(object sender, RoutedEventArgs e)
{
      this.bindingForGridTextBoxes = 
                new BindingHelper(LayoutRoot, typeof(TextBox), TextBox.TextProperty);
      this.DataContext = viewModel;
}

then whereever you need to ensure the bindings are up-to-date, e.g. when one of the cheeky non-framework Application Bar buttons are clicked;

this.bindingForGridTextBoxes.UpdateAllBindings();

wp7 Keyboard helper as a behavior

Thanks to a number of comments regarding the problems I had with the ApplicationBar and the keyboard I’ve decided to apply some of the ideas to my previous post (thanks everyone for the comments) about a keyboard helper to create a self contained keyboard tab helper behavior (mouthful). I’ve posted the full code and binaries, Wp7KeyboardSource.zip
but essentially all you now have to do is;

<Grid x:Name=ContentGrid Grid.Row=1>

  <i:Interaction.Behaviors>

    <keyboard:KeyboardTabHelperBehavior />

  </i:Interaction.Behaviors>

  <StackPanel Orientation=Vertical>

    <CheckBox IsTabStop=True TabIndex=4 Content=Some check/>

    <TextBox TabIndex=1 Text=start here/>

    <TextBox IsTabStop=True Text=Won’t tab here cause not set tabindex/>

    <TextBox IsEnabled=False TabIndex=2 Text=not here cause disabled/>

    <TextBox TabIndex=3 Text=next stop here/>

  </StackPanel>

</Grid>

 …and that’s it, no code behind, no adding of event handlers. Just set up your tab index and stops and it will take care of the rest.

Wp7 vs keyboard vs ApplicationBar vs binding

As you may have read in my previous posts I’m currently trying to iron out some nagging issues with Windows Phone 7 keyboard (SIP). Another problem I’ve hit is when using it in combination with binding and the ApplicationBar. My scenario is straight forward, I have a TextBox for the user’s name which, via binding, changes a view model’s representation of the name (and vice versa). I then have what amounts to a save button in the Application Bar (application bar icon button). When I press the save button I want; a) the keyboard to disappear b) the view model updated with the current text entered for the user name. Sounds simple, and yet it doesn’t work. Making the keyboard disappear is easy enough, I’ve extended the Keyboard helper class to have a HideKeyboard method – which simply does page.Focus(). So what’s the problem? When the save button is pressed it;

  1. calls HideKeyboard which sets the focus to the page
  2. which in turn causes the text box to lose focus and fire the OnPropertyChanged for data binding
  3. calls my SaveName service.

Again seems simple, but the problem is the timing of the events. What actually happens is the execution order is 1->3->2. Why? Well the binding events are only executed once control returns from the function that caused the focus to change. Therefore my service is trying to save the name before the name has been updated, argh! The simplest solution I can think of (please say if you have a better method) is this hack;

void Default_Loaded(object sender, RoutedEventArgs e)
{

    this.keyboardHelper = new KeyboardHelper(this, LayoutRoot);
    this.keyboardHelper.AddKeyUpHander(typeof(TextBox), TabControls_KeyUp);
    this.DataContext = viewModel;
    this.viewModel.PropertyChanged +=
        new PropertyChangedEventHandler(viewModel_PropertyChanged);
}


void saveButton_Click(object sender, EventArgs e)
{
    // hide the keyboard
    this.keyboardHelper.HideKeyboard();
    // [Edit] If you edit one control and then tab to the next this won't work
    // because the 1st control fires the property change but we've not yet pressed saved
    // so I now have to push the values into the view model, i.e. lose some of the clean adv of binding
    this.viewModel.Name = TextBoxName.Text;

    // [Edit 2] Please see comments; 'SS' suggested queing the save via the dispatcher, which is much nicer
    // I'm not sure if you can guarantee the binding will occur first but it's much nicer
    //  Dispatcher.BeginInvoke(() => viewModel.VerifyProfile());
    // remember that we actually want to verify this change
    this.doesWantToVerify = true;
}

private bool doesWantToVerify;
void viewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // some view model property has changed but 
    // did we really want to verify as well?
    if (doesWantToVerify)
    {
        doesWantToVerify = false;
        viewModel.VerifyProfile();
    }
}

So long?

Afer many years of faithful service Windows Spaces’ team have removed blog stats which has made it very difficult for me to justify using it. So I’m now looking at two other blog engines tumblr and wordpress, join me there and let me know which you prefer.