Tag Archives: XAML

Binding IsSelected Method in the ListView Control in WinRT

Basically, it’s not possible. However, this is the best (and only that works) workaround that I found.

Subclass the Listview

I tried everything. Absolutely everything.

I tried straightforward binding – that doesn’t work for IsSelected.
I tried using WinRT Xaml Toolkit – didn’t work.
I tried using Setters – they don’t work for WinRT.

Finally, I came across this solution; here’s the listview subclass (stolen directly from here: http://stackoverflow.com/questions/15994021/listviewitem-isselected-binding-works-for-wpf-but-not-for-winrt):

    public class ListViewEx : ListView
    {
        protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            
            ListViewItem listItem = element as ListViewItem;
            Binding binding = new Binding();
            binding.Mode = BindingMode.TwoWay;
            binding.Source = item;
            binding.Path = new PropertyPath("IsSelected");
            listItem.SetBinding(ListViewItem.IsSelectedProperty, binding);
        }
    }

Obviously this does restrict the IsSelected property name. My class looks something like this:

    public class Person
    {
        public string Name { get; set; }
        …
    }

I didn’t want to add an IsSelected property to this; because it doesn’t directly relate to the entity. My solution was to wrap this inside a class such as this:

    public class SelectableItem<T> : INotifyPropertyChanged
    {
        private T _item;
        public T Item 
        {
            get { return _item; }
            set
            {
                _item = value;
                RaisePropertyChanged();
            }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;                
                RaisePropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName] string name = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
}

And build it like this:

                List<Person> population = GetPeople();
                SelectablePeople = new ObservableCollection<SelectableItem<Person>>(population
                    .Select(n => new SelectableItem<Person>() { Item = n, IsSelected = false }).ToList());

So, finally, bind the collection to the new subclassed listview like this:

        <controls:ListViewEx x:Name="ItemListView" Grid.Column="0" Grid.Row="1"
                        ItemsSource="{Binding SelectablePeople}"                        
                        SelectionMode="Multiple"                        
                        Width="Auto" Height="Auto" >

            <controls:ListViewEx.ItemTemplate>
                <DataTemplate x:Name="MyTemplate">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock                            
                            Text="{Binding Item.Name}"/>
                    </StackPanel>
                </DataTemplate>
            </controls:ListViewEx.ItemTemplate>

        </controls:ListViewEx>

WinRT Data Binding Using MVVM

How to bind Windows 8 XAML to a View Model. Although this post is based on an example using MVVM Cross, it will work for any MVVM framework, or even a customised one.

The Problem

I have a collection of data that I want to display in a customised format. My architecture is MVVM (using MVVM Cross).

Architecture

The principle here is that my data is stored in a model, but shaped in the ViewModel into a digestible format for the view. In my specific example, I have a list of people, and based on a specific criteria, I want to display a selection of these people in the view. For the sake of this article, I want to display people with a name starting with “D”.

Implementation

My model looks something like this:

    public class Person
    {
        #region Basic attributes
        public string Name { get; set; }

When my ViewModel is shown, I override an initialise method. Whilst this is not part of MVVM Cross per-se, it is basically a call to a custom initialise from the default `Init`:

private IEnumerable<Person> _people;
public IEnumerable<Person> People
{
    get { return _people; }
    set
    {
        _people = value;
        RaisePropertyChanged(() => People);
    }
}

// Override custom init method
protected override void RealInit(NavigationParameter parameter)
{            
    var population = Mvx.Resolve<Population>();
    People = population.Where(p => p.Name.StartsWith("D"));
}

So, my ViewModel now contains the correct, shaped data, I can just bind this:

    <Page.Resources>
        <DataTemplate x:Name="PeopleTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>    
    </Page.Resources>

    …


    <ListView x:Name="ItemListView" 
                      ItemsSource="{Binding People}"
                      Width="Auto" Height="Auto" 
                      ItemTemplate="{StaticResource PeopleTemplate}" 
                      ShowsScrollingPlaceholders="False"                          
                      />

And that should work.

Updating a Progress Bar using MVVM Cross

As usual with these posts, although the specific code in the article relates to MVVM Cross, it should be applicable to any MVVM framework. Where it is specific, I’ll try to flag that up.

The Scenario

In the current game that I’m writing in MVVM Cross (yes, that’s right – a game), I have a situation where the user selects to create a “New Game” and the game world needs to be generated. As this can take some time, I want to display a progress bar. Roughly speaking, the process flow is as follows:

On the Menu Page, the User selects “New Game”.
The Menu View Model calls a service that creates the game world.
It then calls the Main Page View Model to display the main page.

The Problem

Basically, communicating between view models without tightly coupling them together.

That’s what messages are for isn’t it?

Yes.

Here’s my implementation.

First step is to add the progress bar to the screen that you want to update:

<views:MvxStorePage
    x:Class=…
    xmlns:converters="using:MyGame.Converters"
    mc:Ignorable="d">

    <views:MvxStorePage.Resources>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConv"/>    
    </views:MvxStorePage.Resources>

    …

    <ProgressBar Value="{Binding LoadingProgress}" Maximum="{Binding TotalProgress}" Margin="20" Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConv}}"/>

There are three properties bound here: None exist yet. Obviously, if you want the progress bar to always display, you might not need all three.

Let’s create the properties in the VM:

        private bool _isLoading = false;
        public bool IsLoading
        {
            get { return _isLoading; }
            set
            {
                _isLoading = value;
                RaisePropertyChanged(() => IsLoading);
            }
        }

        private int _loadingProgress = 0;
        public int LoadingProgress
        {
            get { return _loadingProgress; }
            set
            {
                _loadingProgress = value;
                RaisePropertyChanged(() => LoadingProgress);
            }
        }

        private int _totalProgress = 0;
        public int TotalProgress
        {
            get { return _totalProgress; }
            set
            {
                _totalProgress = value;
                RaisePropertyChanged(() => TotalProgress);
            }
        }

You will also need to declare the BooleanToVisiblityConverter:

    public class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return (bool)value ? Visibility.Visible : Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

Now there’s something to bind to. Next, set-up the messenger.

Messenger

You need to register the messenger object. I have a base model that I do this in, but anywhere before you use it is fine:

Mvx.LazyConstructAndRegisterSingleton<IMvxMessenger, MvxMessengerHub>();

(Warning: MVVM Cross specific)
A caveat here; if you use something like `RegisterType` to register the messenger object, that will also (appear to) work. However, it won’t actually work; it will create a fresh instance of the messenger object each time. If you decide to do it that way then you will need to inject the messenger object into the subscriber and publisher (it has to be the same instance).

Next, you need to create the message:

    class UpdateProgressMessage : MvxMessage
    {
        public UpdateProgressMessage(object sender, int currentProgress, int totalProgress) : base(sender)
        {
            CurrentProgress = currentProgress;
            TotalProgress = totalProgress;
        }

        public int CurrentProgress { get; set; }
        public int TotalProgress { get; set; }
    }

This isn’t much, but the important thing is the constructor. Okay, now let’s subscribe to that message at the start of the task:

_subscriptionTag = Messenger.Subscribe<UpdateProgressMessage>(UpdateProgress);

(A note on `_subscriptionTag` later)

`UpdateProgress` is a method defined like this:

        private void UpdateProgress(UpdateProgressMessage updateProgressMessage)
        {            
            LoadingProgress = updateProgressMessage.CurrentProgress;
            TotalProgress = updateProgressMessage.TotalProgress;
            IsLoading = (updateProgressMessage.CurrentProgress > 0 &amp;&amp; 
                updateProgressMessage.TotalProgress != updateProgressMessage.CurrentProgress);

        }

Notice that you accept the `UpdateProgressMessage`.

That note on `_subscriptionTag`

Firstly, _subscriptionTag is a class level variable, defined like this:

private MvxSubscriptionToken _subscriptionTag;

Once the task is complete you can unsubscribe. For MVVM Cross specifically, the subscription uses weak references, meaning that as soon as `_subscriptionTag` goes out of scope, it will be garbage collected, and will effectively unsubscribe (which is why it needs to be class level in the first place). Having said that, personally, I prefer things to happen in code when I tell them to, and not at some undefined and unpredictable point in the future; so, to unsubscribe:

Messenger.Unsubscribe<UpdateProgressMessage>(subscriptionTag);

Publish

Finally, just wire in the publish code. I have a helper method that instantiates the services and calls the game setup code, but this should work anywhere in the application:

Messenger.Publish<UpdateProgressMessage>(new UpdateProgressMessage(this, count, total));

Because `IMvxMessenger` is registered as a singleton, once you resolve it, you should be able to publish this from anywhere.

A Word About Threading

Okay, so this will all work, but where the task runs on the UI thread, you probably won’t see it update. Consequently, I start a new task for my long running process. Remember that if you do this, then subscribing to messages on the main thread may not work.

Conclusion

Okay, so now I have a progress bar for the set-up of my game. Like I said at the start, I think this should work for any architecture that supports IoC and messaging, but MVVM Cross seems to handle this very neatly.

Windows Tile Updater (Part 7 – Multibinding command parameters)

We left the last post where the Tile Updater could update text, or images, but we basically had to choose which at design time. In this post, I’m going to pass through the image and text, and have the command work out which to update.

Note: you can have both image and text in live tiles. Look out for that in a future post.

Multibinding

The first thing to know about multibinding for WinRT is that it doesn’t exist. However, to get around this, we can simply take the same approach that we do with a function – a function can only return one value, but that value can be a class; so we’ll bind to the VM (one of the advantages of exposing a static singleton instance of the VM):

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding MVM}">Update</Button>        

The command itself needs to look something like this for now:

        public bool CanExecute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;
            if (mvmInst == null) return false;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath) &amp;&amp; string.IsNullOrWhiteSpace(mvmInst.DisplayText))
                return false;
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            MainViewModel mvmInst = (MainViewModel)parameter;

            if (string.IsNullOrWhiteSpace(mvmInst.ImagePath))
                TileUpdater.Model.UpdateTile.UpdateTileText(mvmInst.DisplayText);
            else
                TileUpdater.Model.UpdateTile.UpdateTileImage(mvmInst.ImagePath);
        }

There’s a couple of points here:
1. The CanExecute will not prevent the command from firing where neither parameter has a value.
2. It doesn’t disable the button when this occurs.

And that’s it – we now have a command that can accept multiple parameters and update either image or text depending on what is displayed.

Conclusion

Okay, strictly speaking, this is not multi-binding. It does however, solve the problem. I suppose the design question would be: does it introduce a tighter coupling than multi-binding?

It definitely does; however, with a bit of manipulation, you could introduce a mini-VM that just had the parameters that you need. However, for most cases, I would think that it was fine to just pass the VM to the command. We’ll see if this comes back to bite me when we start putting some unit tests in place.

Windows Tile Updater (Part 6 – Binding a command parameter)

We’re still missing functionality to show the text, or show the text and an image where both are specified.

Add text

Let’s start with the text field. It’s currently just hard coded – that’s pretty straightforward:

        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="{Binding DisplayText, Mode=TwoWay}" Margin="10"/>
        </StackPanel>

Next, let’s hook this up to the command.

<Button Grid.Row="2" Command="{Binding UpdateCommand}" CommandParameter="{Binding DisplayText}">Update</Button>

So that works, and the logic to show the text tile is quite straightforward:

        public static void UpdateTileText(string text)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Text01);

            XmlElement textNode = (XmlElement)xmlDoc.GetElementsByTagName("text")[0];
            textNode.InnerText = text;

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

So, we can call this, or we can call the UpdateImage. At the moment, we can’t call both. In the next post I’ll look at how we can do this using Multibinding.

Windows Tile Updater (Part 5 – sharing XAML)

In Part 4 we finished with an MVVM app, running on both Windows 8 and Windows Phone. In this post I’m going to explore the idea of using the same XAML.

Is this a good idea?

The very short answer is probably “NO!”. The problem is that in anything but the most trivial of applications, the XAML will need to differ. In this application, it probably doesn’t matter, but then, it wouldn’t kill anyone to maintain two sets of very trivial XAML either.

My approach to this, and to the above question is to create a custom user control, and then use that in both applications. The good thing about this is that it does make sense to share user controls (to me anyway).

New UserControl

We’ll create a View directory in the shared project, and add the UserControl there:

NewView

It should look like this:

<UserControl
    x:Class="TileUpdater.View.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TileUpdater.View"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    DataContext="{Binding MVM, Source={StaticResource MainViewModel}}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="0">
            <TextBlock FontSize="30" Margin="10">Image</TextBlock>
            <TextBox Text="{Binding ImagePath}" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="My Phone Number: 123456 890 12" Margin="10"/>
        </StackPanel>

        <Button Grid.Row="2" Command="{Binding UpdateCommand}">Update</Button>
    </Grid>
</UserControl>

You’ll be familiar with this XAML by now. Nothing had changed, it’s the same. In the Phone app, we’ll replace the whole XAML with the following:

<Page
    x:Class="TileUpdater.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TileUpdater"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:view="using:TileUpdater.View"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <view:MainView/>
</Page>

And the Windows 8 XAML with this:

<Page
    x:Class="TileUpdater.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TileUpdater"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:view="using:TileUpdater.View"
    mc:Ignorable="d">    

    <view:MainView/>
</Page>

Other than the theme, they are the same. You could obviously just have MainPage in the shared project, but personally, I don’t believe that is extensible; if you do so, you run the risk of ending up with an overly complex XAML file trying to cater for each separate project type.

Conclusion

Just a short post this time. In the next post on this, I’m going to add the missing functionality. This should be far easier now that the whole application is basically inside the shared project.

Windows Tile Updater (Part 4 – rationalise the code)

From Part 3 of this tutorial, we finished with a small program running on both Windows 8.1 and Phone 8. It shared most of its business logic, but replicated the XAML. It had an ugly even handler to deal with the single action that it performed. In this post, I’m going to attempt to change this to use the MVVM architecture. I’m also going to do this without using a third party framework.

MVVM

If we are to migrate this to an MVVM pattern, then we will need to do the following:
1. Create a view model
2. Bind the view, to the view model
3. Create a model (the business / tile logic that we have is already a model of sorts).

View Model

I usually find it easier to work from the View Model first.

Note:
I’d normally create this as a separate PCL, but it would appear that shared projects are limited in that they cannot reference any other projects. I found no documentation from MS to say why, or even confirm this was the case. This may well be the subject of a future post.

Anyway, we can create the view model in the shared project:

createmodelinsharedproject

Let’s start with the properties:

namespace TileUpdater.ViewModel
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private static MainViewModel _mvm;
        public static MainViewModel MVM
        {
            get
            {
                if (_mvm == null)
                    _mvm = new MainViewModel();

                return _mvm;
            }
        }

        private string _imagePath = @"c:locationimage.png";
        public string ImagePath
        {
            get { return _imagePath; }
            set
            {
                SetProperty<string>(ref _imagePath, value);
            }
        }

        private string _displayText;
        public string DisplayText
        {
            get { return _displayText; }
            set
            {
                SetProperty<string>(ref _displayText, value);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
        {
            if (Equals(storage, value))
            {
                return false;
            }

            storage = value;
            OnPropertyChanged<T>(propertyName);
            return true;
        }

        private void OnPropertyChanged<T>([CallerMemberName]string caller = null)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(caller));
            }
        }
    }
}

And bind them to the Windows 8 view:

<Page
    x:Class="TileUpdater.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TileUpdater"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"    
    DataContext="{Binding MVM, Source={StaticResource MainViewModel}}">
       
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="0">
            <TextBlock FontSize="30" Margin="10">Image</TextBlock>            
            <TextBox Text="{Binding ImagePath}" Margin="10"/>
        </StackPanel>
        
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="My Phone Number: 123456 890 12" Margin="10"/>
        </StackPanel>

        <Button Grid.Row="2" Click="Button_Click">Update</Button>
    </Grid>
</Page>

Quick explanation

I simply created a singleton instance of the view model. Did I have to create a singleton? No – there’s a hundred different ways I could have done this; if I had several view models then you could create a small dictionary with them in (in the style of MVVMLight). I specifically didn’t want to use a framework here, and I didn’t want to overcomplicate – say what you like about singletons, but they are simple.

Now let’s bind the phone

Take the XAML in the Windows 8 XAML and paste it into MainPage.xaml:

…
DataContext="{Binding MVM, Source={StaticResource MainViewModel}}">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="0">
            <TextBlock FontSize="30" Margin="10">Image</TextBlock>            
            <TextBox Text="{Binding ImagePath}" Margin="10"/>
        </StackPanel>
        
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="My Phone Number: 123456 890 12" Margin="10"/>
        </StackPanel>

        <Button Grid.Row="2" Click="Button_Click">Update</Button>
    </Grid>

Command Binding

The next step is to bind the commands. MVVM Light allows RelayCommand for this purpose, but let’s see what we can do on our own.

The first step is to bind the command. For now, let’s just do this in the Windows 8 MainPage.xaml:

        <!--<Button Grid.Row="2" Click="Button_Click">Update</Button>-->
        <Button Grid.Row="2" Command="{Binding UpdateCommand}">Update</Button>

We’ve now bound the command, but have nothing to bind. Without a framework, this is very much a matter of rolling your own. First, you need to add the command:

addupdatecommand

The implementation is quite simple:

namespace TileUpdater.ViewModel
{
    class UpdateCommand : ICommand
    {
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            TileUpdater.UpdateTile.UpdateTileImage();
        }
    }
}

Finally, just link this up the the ViewModel (TileUpdater.Shared):

        private ICommand _updateCommand;
        public ICommand UpdateCommand
        {
            get
            {
                if (_updateCommand == null)
                {
                    _updateCommand = new UpdateCommand();
                }
                return _updateCommand;
            }
            set { _updateCommand = value; }
        }

Needless to say that we need to make the same change in the phone app. The XAML for MainPage should be exactly the same:

        <!--<Button Grid.Row="2" Click="Button_Click">Update</Button>-->
        <Button Grid.Row="2" Command="{Binding UpdateCommand}">Update</Button>
    </Grid>

What about the Model – isn’t this just VVM?

Okay – so, we’re now basically using the MVVM pattern. We don’t technically have a Model, though. Actually, TileUpdater is really the Model, so let’s simply call it one:

justcallitamodel

Conclusion

Now we’re running an MVVM pattern and sharing most of the code. However, there’s a lot of duplicate XAML, and the UI is a bit scrappy, so We’ll have a look at that in the next post.

Windows Tile Updater (Part 3 – Move the code to a shared project and create the Phone App)

In the third part of my series on creating a universal app, I’m going to transfer the code that we created in part 2 and move it into a shared project.

If you want to have a look at the source code, or just use it for something, it’s here:

https://windowstileupdater.codeplex.com/

So far, we have code to update the tile, but it’s in the Windows 8.1 app. Let’s just move that to the shared project:

movetoshared

TileUpdater.cs looks like this:

    public class UpdateTile
    {
        private static void UpdateTileImage(string image)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Image);

            XmlElement imageNode = (XmlElement)xmlDoc.GetElementsByTagName("image")[0];
            imageNode.SetAttribute("src", string.Format("ms-appx://{0}", image));

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

        public static void UpdateTileImage()
        {
            string image = "/Assets/test.png";
            UpdateTileImage(image);
        }
    }

You might notice this is precisely the same code. The button click event on the main page looks like this now:

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TileUpdater.UpdateTile.UpdateTileImage();            
        }

Now, run again and the behaviour should remain the same. This isn’t much – I mean, if you’re reading this and have just found out how to separate code from the main program then you might be reading the wrong blog. So, let’s try wiring up the phone app. We’ll start with the XAML:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="0">
            <TextBlock FontSize="30" Margin="10">Image</TextBlock>
            <TextBox Text="c:locationimage.png" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="My Phone Number: 123456 890 12" Margin="10"/>
        </StackPanel>

        <Button Grid.Row="2" Click="Button_Click">Update</Button>
    </Grid>

The XAML is familiar – I copied it verbatim from the Win 8 app (as I said in the last post, I will try to rationalise this a little, although other than in a very trivial app such as this, you would probably want the XAML to be different). And the code behind:

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TileUpdater.UpdateTile.UpdateTileImage();
        }

And, it works:

phoneappstartscreen

Did it just work – just like that?

Well, no.

Okay – there was some fiddling – here’s the fiddling:
1. The app will (again) not be pinned to the start screen, you’ll need to use the emulator to do so.
2. The tile will, again, initially be a small square (half the size of a wide tile – 150 x 150); this will need to be a wide tile, and to do so, you need to press and hold and the first reduce the size, before increasing to a wide tile.

Conclusion

Okay – so, we now have a Windows Store and Phone App. There’s a common codebase (admittedly it’s a bit scrappy), and the phone app took around 20 seconds.

In the next post I’m going to tidy up the code and investigate options for using shared XAML.

Windows Tile Updater (Part 2 – creating the project and tile update logic)

In my first post of this series I looked at some considerations of designing a store / phone app. This post will cover the basics of creating a new Phone / Store app.

Universal App

The new type of application is called a Universal App – so let’s create one:

NewUniversal

I’m going to select a blank app, and create the project. What this gives me is a solution containing three separate projects.

UniversalSolutionExplorer

If I select to run the Windows app I get a blank Windows Store App, and if I select to run the phone app I get a blank phone app. The shared project can be used to create a common application lifecycle, share events and logic. However, the UI is separate (ish – we’ll come back to that in a later post). Let’s start with the Window 8 app

Create the tile image

You can’t update a tile that doesn’t exist; for this example, we’re going to update the wide tile, so you’ll need one. Just create any image 310 x 150 as a png file and point your Windows app at it:

universalmanifest

The app will use a wide tile if it is present on the first install only. If you miss this, then uninstall using the following option:

universaluninstall

Create the tile updater

Next, create another tile image – just copy the first and change the text or draw something on it. Add this to your Windows 8.1 project, and call it test.png (place it under the Assets folder).

The code to update a tile in Windows 8 is as follows:

        private static void UpdateTileImage(string image)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Image);

            XmlElement imageNode = (XmlElement)xmlDoc.GetElementsByTagName("image")[0];
            imageNode.SetAttribute("src", string.Format("ms-appx://{0}", image));

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

A little (actually not so little) gotcha is that Live Tiles don’t work in the simulator (http://social.msdn.microsoft.com/Forums/windowsapps/en-US/8357462e-f97b-48c2-8fea-57d47c7ead2a/do-live-tiles-updated-properly-in-the-simulator?forum=toolsforwinapps)

Testing is further complicated because tiles are not automatically pinned to the start menu; so you may deploy and not see your tile. Even worse, I noticed a few times that despite the tile not being on the start screen, on searching for it, Windows claimed it was (so I had to un-pin and re-pin).

Just write the code for Windows

Okay, so let’s just create the tile updater inside Windows 8.1 (this is the code for MainPage.xaml.cs):

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            UpdateTileImage();
        }

        private void UpdateTileImage(string image)
        {
            XmlDocument xmlDoc = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Image);

            XmlElement imageNode = (XmlElement)xmlDoc.GetElementsByTagName("image")[0];
            imageNode.SetAttribute("src", string.Format("ms-appx://{0}", image));

            Windows.UI.Notifications.TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
            TileNotification tileNotification = new TileNotification(xmlDoc);
            tileUpdater.Update(tileNotification);
        }

        public void UpdateTileImage()
        {
            string image = "/Assets/test.png";
            UpdateTileImage(image);
        }

If you need the XAML, it’s here:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="0">
            <TextBlock FontSize="30" Margin="10">Image</TextBlock>            
            <TextBox Text="c:locationimage.png" Margin="10"/>
        </StackPanel>
        
        <StackPanel Orientation="Horizontal" Margin="20" Grid.Row="1">
            <TextBlock FontSize="30" Margin="10">Text</TextBlock>
            <TextBox Text="My Phone Number: 123456 890 12" Margin="10"/>
        </StackPanel>

        <Button Grid.Row="2" Click="Button_Click">Update</Button>

Conclusion

You now have a little program for Windows 8.1 that updates tiles based on a button click. In the next post, we’ll move this into the shared project and call it from the phone app, too. In later posts, I’ll change and refactor the architecture, too.

Convert Monogame to Monogame with XAML

Some time ago, I blogged about the importance of creating a “Monogame With XAML” project. Before I’d written this, I’d started a long running project, and realised that I needed XAML (for reasons already indicated). So, is it possible to convert? YES!

Is it easy? Actually, it’s not too bad; but to save anyone else (and my future self) the hastle of working out how, I’ve broken it down into 7 easy steps. (Below, MyGame refers to your game namespace).

1. Add app.xaml as a blank xaml page. Once it’s added, change the BuildAction to ApplicationDefinition:

Image

2. Clear the XAML from the page, and replace with the following:

<Application
    x: Class="MyGame.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns: x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns: local="using:MyGame">

    <Application.Resources >
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!--
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source ="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>
    </Application.Resources >
</Application>

3. StandardStyles.xaml referenced above will not exist. Create a new XAML file in the appropriate directory (the one in this example is in a Common subdirectory. This should look something like the following (although given that these are styles, you may have different ideas):

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- Non-brush values that vary across themes -->

    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Default">
            <x:String x:Key="BackButtonGlyph">&#xE071;</x:String>
            <x:String x:Key="BackButtonSnappedGlyph">&#xE0BA;</x:String>
        </ResourceDictionary>

        <ResourceDictionary x:Key="HighContrast">
            <x:String x:Key="BackButtonGlyph">&#xE071;</x:String>
            <x:String x:Key="BackButtonSnappedGlyph">&#xE0C4;</x:String>
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>

    <x:String x:Key="ChevronGlyph">&#xE26B;</x:String>
...
</ResourceDictionary>

If you’re unsure about what to put in here then just create a blank store app and lift this file.

4. Next, you need to edit the code behind for the new App.Xaml file. In App.Xaml.cs, you should have the following code:

using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227

namespace MyGame
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            InitializeComponent();
            Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            var gamePage = Window.Current.Content as GamePage;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (gamePage == null)
            {
                // Create a main GamePage
                gamePage = new GamePage(args.Arguments);

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // TODO: Load state from previously suspended application
                }

                // Place the GamePage in the current Window
                Window.Current.Content = gamePage;
            }

            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

            // TODO: Save application state and stop any background activity

            deferral.Complete();
        }
    }
}

5. GamePage referenced above doesn’t exist; create a new Page, called GamePage.xaml, and paste the following Xaml into it:

<SwapChainBackgroundPanel
    x:Class="MyGame.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyGame"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
    </Grid>

</SwapChainBackgroundPanel>

6. Next, press F7 to get to the code-behind for GamePage.Xaml. In GamePage.Xaml.cs, paste the following code:

    public sealed partial class GamePage : SwapChainBackgroundPanel
    {
        readonly GameEngine _game;

        public GamePage(string launchArguments)
        {
            this.InitializeComponent();

            // Create the game.
            _game = XamlGame<GameEngine>.Create(launchArguments, Window.Current.CoreWindow, this);
        }
    }

This should link the whole thing back to your initial GameEngine that MonoGame uses.

7. Finally, locate Program.cs and either comment out the code, or just delete it.

DONE

You should now find that your game runs exactly as before, except you now have XAML capabilities.

Please feel free to add any comments for anything that I might have missed, or improvements you may have on this process. Also, feel free to leave comments such as: “Yes, this worked!”.