Category Archives: XAML

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.

Using data binding inside monogame to control ad control display

I’ve already blogged a few times on using monogame with XAML. One thing that occurred to me recently was that I could leverage this in order to better control when the ad control appears in one of my games. Basically, my idea was that I could bind the main game page to a model, which determined whether the ad would be displayed.

Obviously, the difficulty here is that you need to pass the view model around your app. Monogame doesn’t seem to be very good at allowing you to do that, so I decided to use this approach (in app.xaml.cs):

    sealed partial class App : Application
    {
        private static GamePageViewModel _gamePageViewModel;
        public static GamePageViewModel GamePageViewModel
        {
            get
            {
                if (_gamePageViewModel == null)
                {
                    _gamePageViewModel = new GamePageViewModel();
                }

                return _gamePageViewModel;
            }
        }

A couple of notes on that code:
1. Yes, I could have simply instantiated the viewmodel at the start of the app.
2. Yes, it is static. This is so you can access it elsewhere.

The GamePageViewModel isn’t particularly noteworthy:

namespace MyGame.ViewModel
{
    public class GamePageViewModel : INotifyPropertyChanged
    {
        private bool _showAds;
        public bool ShowAds
        {
            get { return _showAds; }
            set
            {
                _showAds = value;
                RaisePropertyChanged( "ShowAds");
            }
        }

        private void RaisePropertyChanged( string caller)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged( this, new PropertyChangedEventArgs(caller));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

I do need to set this in code though; so when you display the GamePage:

         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);

                // Set the DataContext to the static instance of the ViewModel
                gamePage.DataContext = App.GamePageViewModel;

You need to bind the ad control (use somthing like this – I haven’t detailed the code for the converter, but I’m sure 3 seconds of Internet searching will reveal a few thousand examples):

               
<UI: AdControl x: Name ="adControl"                                          
ApplicationId ="appid"
      AdUnitId ="appunitid"      
Width ="728"
      Height ="90"
      IsAutoRefreshEnabled ="True"                         
      Margin ="5"      
      Visibility ="{Binding ShowAds , Converter ={StaticResource BoolToVisibilityConv}}">
/>

What this allows me to do, from ANYWHERE in the game is this:

               
         private async static void purchaseCommandInvoked(Windows.UI.Popups.IUICommand command)
        {
            bool success = await License.PurchaseApp();

            if (success)
            {
                // Updating the view model here!
                App.GamePageViewModel.ShowAds = false;
            }
        }

Conclusion

So, nothing new here, but using binding inside Monogame didn’t occur to me immediately, so there must be a least some people in the same boat.

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!”.

Implementing single cell copy and full row Item Selection in WPF DataGrid

Recently, I came across a strange problem with a DataGrid while using the MVVM-Light pattern. The problem was that I needed to implement two, seemingly similar pieces of functionality:

1. To copy any given cell in the data grid
2. To search the database, based on a specific piece of data in the selected row of the datagrid (regardless of which cell was selected).

To implement the Copy feature was unbelievably easy – you don’t even need a custom command; just add the following setting to the DataGrid:

SelectionUnit ="CellOrRowHeader"

And the following context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
       <MenuItem Command="Copy"/>                    
    </ContextMenu>
</DataGrid.ContextMenu>

And the copy is done!

So, next, I wanted to implement the custom search. I needed to identify the currently selected row in my ViewModel, so I added a new property:

        private MyDataClass _selectedItem;
        public MyDataClass SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                RaisePropertyChanged(() => SelectedItem);
            }
        }

I then bound this to the selected item of the datagrid, like this:

     < DataGrid ItemsSource ="{ Binding Path =MyDataCollection}"                   
                  SelectedItem="{ Binding Path =SelectedItem}"                   
                  SelectionUnit ="CellOrRowHeader"  
&#91;/sourcecode&#93;

And finally, created my command:

&#91;sourcecode language="csharp"&#93;
         public RelayCommand MyCommand { get ; private set ; }
&#91;/sourcecode&#93;

In the constructor, initialised it:

&#91;sourcecode language="csharp"&#93;
     this.MyCommand = new RelayCommand (() => this.MyCommandFunc());

Created the function:

         private void MyCommandFunc()
        {
            QueryDB(SelectedItem.ValueOne);
        }         

And, finally, setup the context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
         <MenuItem Command ="Copy"/>                    
         <MenuItem Header ="My Funky Command" Command="{Binding MyCommand}"/>
    </ContextMenu>
</DataGrid.ContextMenu>

But this didn’t work! (Queue dramatic music).

The problem is down to this:

SelectionUnit ="CellOrRowHeader"

So, change it to:

SelectionUnit="FullRow" 

And it works again… but now copy doesn’t work, because it copies the FULL ROW!

So, the two features are incompatible?

I did find a workaround which doesn’t breach the separation of concerns. Please note that, although this does work, and does not breach separation of concerns, it may or may not be the best way of doing it. If you have, or know of, a better way the PLEASE leave a comment, or mail me and let me know.

The Workaround

Instead of binding the SelectedItem property, bind the Tag property of the grid:

< DataGrid ItemsSource ="{ Binding Path =MyDataCollection}" Tag="{ Binding Path =SelectedItem}" SelectionUnit ="CellOrRowHeader" [/sourcecode] Now, we need a little code-behind, which must remain agnostic to the ViewModel: [sourcecode language="csharp"] private void DataGrid_SelectedCellsChanged( object sender, SelectedCellsChangedEventArgs e) { (( DataGrid)sender).Tag = ((DataGrid)sender).SelectedCells.FirstOrDefault().Item; } [/sourcecode] Now, because the SelectedItem is bound in the view to the Tag, updating the Tag, updates the SelectedItem. This means that when you call your function (as described above): [sourcecode language="csharp"] private void MyCommandFunc() { QueryDB(SelectedItem.ValueOne); } [/sourcecode] SelectedItem is now set. Conclusion

Whilst I can see why this works the way it does, it doesn’t seem sensible that I need to jump through so many hoops to get this to work without breaking the separation of concern. It may just be a quirk with the DataGrid, but it feels like a hack – which I don’t like. Nevertheless, ATM it’s the only solution that I can come up with that doesn’t mean directly referencing the View from the ViewModel.

Animation in XAML (Part 5)

Introduction

In this post, I would like to specifically focus on the differences between animations in WPF and in WinRT. Some quick disclaimers: As far as I’m aware, Windows Phone and WinRT are interchangeable where animations are concerned, but I base that only on my efforts to move a specific animation between the two. Consequently I won’t look at Windows Phone.

The Animation

Here’s a sample of the animation to cause the button to spin and disappear from previous posts:

         private void SpinAndDisappear_Click( object sender, RoutedEventArgs e)
        {
           
            Button b = (Button)sender;
           
            DoubleAnimation da = new DoubleAnimation (b.Width, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.WidthProperty, da);

            DoubleAnimation da2 = new DoubleAnimation (b.Height, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.HeightProperty, da2);

            DoubleAnimation da3 = new DoubleAnimation (0, 360, TimeSpan.FromSeconds(.5));           
            RotateTransform transform = (RotateTransform )b.RenderTransform;
            transform.BeginAnimation( RotateTransform.AngleProperty, da3 );
        }

How it Works in WinRT

Okay, so the short answer is: it doesn’t – well, that doesn’t anyway! There are a few reasons why this won’t work in WinRT, but the most annoying one is that WinRT doesn’t support multiple animations on the same element. That is, only one storyboard can be running for a given element at any time.

Before we get into a workaround, so cunning, you could tie a tail to it and call it a fox, let’s look at the size animation in WinRT (as it’s not exactly the same); first the XAML:

             < Button x : Name="SpinAndDisappear" Content ="Don't press me" Click="SpinAndDisappear_Click"
                RenderTransformOrigin ="0.5, 0.5" Height ="100" Width="300"/>

And the code behind:

             UIElement obj = ( UIElement)SpinAndDisappear;

            obj.RenderTransform = new CompositeTransform ();

            var story = new Storyboard ();

            var xAnim = new DoubleAnimation ();
            var yAnim = new DoubleAnimation ();           

            xAnim.Duration = TimeSpan.FromSeconds(2);
            yAnim.Duration = TimeSpan.FromSeconds(2);           

            xAnim.To = 0;
            yAnim.To = 0;
           
            story.Children.Add(xAnim);
            story.Children.Add(yAnim);

            Storyboard .SetTarget(xAnim, obj);
            Storyboard .SetTarget(yAnim, obj);

            Storyboard .SetTargetProperty(xAnim, "(UIElement.RenderTransform).(CompositeTransform.ScaleX)" );
            Storyboard .SetTargetProperty(yAnim, "(UIElement.RenderTransform).(CompositeTransform.ScaleY)" );
                      
            story.Begin();

I’ve borrowed quite heavily here from this article by Iris Classon:

http://irisclasson.com/2012/06/28/creating-a-scaletransform-animation-in-c-for-winrt-metro-apps/

Okay, so I want to execute two animations at the same time; surely I just do this:

         void SpinAnimation()
        {
            UIElement obj = ( UIElement)SpindAndDisappear;

            obj.RenderTransform = new RotateTransform ();
            var storySpin = new Storyboard ();
            var spinAnim = new DoubleAnimation ();
            spinAnim.Duration = TimeSpan.FromSeconds(2);
            spinAnim.From = 0;
            spinAnim.To = 360;
            storySpin.Children.Add(spinAnim);
            Storyboard .SetTarget(spinAnim, obj);
            Storyboard .SetTargetProperty(spinAnim, "(UIElement.RenderTransform).(RotateTranform.Angle)" );
           
            storySpin.Begin();
        }

And call SpinAnimation after the first StoryBegin()? That did work in WPF. If you do this, what you get is a rotation animation only. As stated before, one element, one animation. The workaround is ingenious and, unfortunately, not my idea:

http://stackoverflow.com/questions/20224307/running-multiple-animations-in-windows-store-app

But here’s how it looks:

         < Frame x : Name="SpindAndDisappearParent" Height ="100" Width ="300"
               RenderTransformOrigin ="0.5, 0.5">
            < Button x : Name="SpinAndDisappear" Content ="Don't press me"Click="SpinAndDisappear_Click"
                RenderTransformOrigin ="0.5, 0.5" Height ="100" Width="300"/>

         </ Frame>

It’s important that the sizes of the parent and child elements are the same; next, just change the SpinAnimation() function like so:

         void SpinAnimation()
        {
            UIElement obj = ( UIElement)SpindAndDisappearParent;

            obj.RenderTransform = new RotateTransform ();
            var storySpin = new Storyboard ();
            var spinAnim = new DoubleAnimation ();
            spinAnim.Duration = TimeSpan.FromSeconds(2);
            spinAnim.From = 0;
            spinAnim.To = 360;
            storySpin.Children.Add(spinAnim);
            Storyboard .SetTarget(spinAnim, obj);
            Storyboard .SetTargetProperty(spinAnim, "(UIElement.RenderTransform).(RotateTranform.Angle)" );
           
            storySpin.Begin();
        } 

Conclusion

As you can see, I’ve rested heavily on the shoulders of giants here (which is another way of saying I’ve basically used other peoples code and ideas). Having said that, this area is virtually deserted as far as internet resources go; that’s why I started this series of articles in the first place.

Hopefully they’ve proved helpful.