Tag Archives: WinRT

WPF Drawing Application

The following is a XAML page that allows the user to draw on it. This was written and tested under a Windows 10 desktop application, but should work for WPF. Here’s the XAML:

        <Grid>
            <Border>
                <Canvas PointerPressed="Canvas_PointerPressed" PointerMoved="Canvas_PointerMoved"
                        PointerReleased="Canvas_PointerReleased"
                        Background="Orange" Name="Canvas" />
            </Border>
        </Grid>

The background is a different colour to identify the canvas.

There’s the code to allow drawing:

        
        Path _currentPath;

        private void Canvas_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {            
            _currentPath = new Path
            {
                Data = new PathGeometry
                {
                    Figures = { new PathFigure
                    {
                        StartPoint = e.GetCurrentPoint((UIElement)sender).Position,
                        Segments = { new PolyLineSegment() }
                    }}
                },
                Stroke = new SolidColorBrush(Colors.Black),
                StrokeThickness = 5
            };

            Canvas.Children.Add(_currentPath);
        }

        private void Canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            if (_currentPath == null) return;

            var pls = (PolyLineSegment)((PathGeometry)_currentPath.Data).Figures.Last().Segments.Last();
            pls.Points.Add(e.GetCurrentPoint((UIElement)sender).Position);
            
        }

        private void Canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            _currentPath = null;
        }

As you can see, it doesn’t do anything for my drawing ability:

drawing

It’s all the code behind and, while I typically shy away from this, it seems to fit well for an application such as this (as the drawing relates more to the view than to anything else).

Handling Input in XNA / MonoGame

This morning I didn’t have internet access and was trying to find this in my notes (which are also my blog posts), and I couldn’t; so purely for my own benefit, the following is a method of handling touch or mouse input in Monogame:

        public void HandleInput()
        {
            ProcessMouseInput();
            ProcessTouchInput();
            ProcessKeyboardInput();
        }

        private void ProcessMouseInput()
        {
            var currentMouse = Microsoft.Xna.Framework.Input.Mouse.GetState();

            if (currentMouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
            {
                HandlePressed(currentMouse.Position, _controlledObject);
            }
        }

        private void ProcessTouchInput()
        {
            var currentTouch = Microsoft.Xna.Framework.Input.Touch.TouchPanel.GetState();

            foreach (var touch in currentTouch.Where(t => t.State == Microsoft.Xna.Framework.Input.Touch.TouchLocationState.Pressed))
            {
                HandlePressed(touch.Position, _controlledObject);
            }


        }

        private void ProcessKeyboardInput()
        {
            var currentKeys = Microsoft.Xna.Framework.Input.Keyboard.GetState();
            if (currentKeys.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Left))
            {
                _handler.GoLeft(_controlledObject);

By changing Pressed to Released, you can detect when the mouse button click / touch finished; however, if you hold your finger / mouse button down, it will only return a single result.

Playing Media in Windows Universal Apps

I recently had cause to write a universal app that has voice capabilities. Hopefully it will shortly be available on the Windows Store.

Adding voice synthesis, while a seemingly basic task, proved to be anything but. What follows is a series of trials and tribulations that I have overcome in order to bring this app to the public!

The Code

Here’s the basic code to get started.

                var voiceStream = await synth.SynthesizeTextToStreamAsync("Hello");
                
                MediaElement mediaElement = new MediaElement();

                mediaElement.SetSource(voiceStream, voiceStream.ContentType);
                mediaElement.AutoPlay = false;
                mediaElement.Volume = 1;
                mediaElement.IsMuted = false;

                mediaElement.Play();

Windows Phone

The first issue I encountered with Windows Phone was the volume. Having maxed out my laptop speakers, I managed get a faint whimper. What I finally deduced is that, for some reason, when the emulator starts, it starts at half volume. To increase it you have to press the phone’s volume buttons (which I initially assumed were just there for aesthetics. Clearly Microsoft haven’t entirely abandoned skeuomorphism.

Phone

The volume controls are the top right buttons (which I happened to know because I have owned a Windows Phone in the past). Once you press it then a more sensible interface appears and you can change either the ringer volume, or the game volume.

Overtalking

Although the code above does work, try calling the code in a loop (or just twice). What happens is that it doesn’t wait for itself to finish.

What I didn’t realise (until I asked this) was that there are some events which supposedly fire when the media element has finished playing.

                var voiceStream = await synth.SynthesizeTextToStreamAsync(toSay);
                
                MediaElement mediaElement = new MediaElement();

                mediaElement.Loaded += mediaElement_Loaded;
                mediaElement.MediaEnded += mediaElement_MediaEnded;
                mediaElement.MediaFailed += mediaElement_MediaFailed;

                mediaElement.SetSource(voiceStream, voiceStream.ContentType);
                mediaElement.AutoPlay = false;
                mediaElement.Volume = 1;
                mediaElement.IsMuted = false;
                
                mediaElement.Play();

I say supposedly, because when I first tried to capture the events, they did nothing. After a bit of searching, it turns out that the element needs to be part of the visual tree! Which of course makes total sense – an AUDIO media element must be part of the VISUAL tree.

In the Visual Tree

The code below now looks for the media element in the visual tree, and if it can’t find one, adds it. It also uses the TaskCompletionSource object to await the audio stream.

            using (SpeechSynthesizer synth = new SpeechSynthesizer())
            {
                var voiceStream = await synth.SynthesizeTextToStreamAsync(toSay);
                
                MediaElement mediaElement;
                
                mediaElement = this.rootControl.Children.FirstOrDefault(m => (m as MediaElement) != null) as MediaElement;
                if (mediaElement == null)
                {
                    mediaElement = new MediaElement();
                    this.rootControl.Children.Add(mediaElement);
                }
                
                mediaElement.SetSource(voiceStream, voiceStream.ContentType);                
                mediaElement.Volume = 1;
                mediaElement.IsMuted = false;

                var tcs = new TaskCompletionSource<bool>();
                mediaElement.MediaEnded += (o, e) => { tcs.TrySetResult(true); };
                mediaElement.Play();

                await tcs.Task;
                
            }

That works. At least, it works on Windows Phone. Because it uses a media element, I thought putting it on a shared XAML page would work… but it doesn’t. Windows 8.1 just sits there quietly and says nothing.

Windows Store

After much trial and error, it occurred to me (prompted by a comment on the above question) that if the problem was down to a deadlock, then destroying and recreating the control might clear this up.

Amazingly, that did seem to work; the working code is:

            using (SpeechSynthesizer synth = new SpeechSynthesizer())
            {
                var voiceStream = await synth.SynthesizeTextToStreamAsync(toSay);

                MediaElement mediaElement;

                mediaElement = rootControl.Children.FirstOrDefault(a => a as MediaElement != null) as MediaElement;
                if (mediaElement == null)
                {
                    mediaElement = new MediaElement();
                    
                    rootControl.Children.Add(mediaElement);
                }

                mediaElement.SetSource(voiceStream, voiceStream.ContentType);
                mediaElement.Volume = 1;
                mediaElement.IsMuted = false;

                var tcs = new TaskCompletionSource<bool>();                
                mediaElement.MediaEnded += (o, e) => { tcs.TrySetResult(true); };               

                mediaElement.Play();                

                await tcs.Task;

                rootControl.Children.Remove(mediaElement);

            }

And this does seem to work on both platforms.

How to Draw a Diagonal Line Using Only XAML (and no path data)

I’ve been playing around with an app to maintain a score. The first thing that I wanted to do was to split the screen, but I wanted a diagonal split; similar to this:

phonescreen

There are a number of ways that this can be achieved; however, this is a method using only XAML. The same method will (I believe) work on Windows 8, WPF and Windows Phone.

First, split the screen into three rows or columns (which depends on how you want the orientation):

        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

This needs to be an odd number of rows / columns if you want the line to be central; additionally, an increased number of rows or columns will result in a smaller incline. Next, draw a transparent rectangle across the middle grid square:

        <Rectangle Name="Placeholder" Grid.Row="1" 
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Opacity="0"/>

Finally, simply draw a line, binding the X2, Y2 values to the height and width of your rectangle:

        <Line Grid.Row="1" 
              X1="0" X2="{Binding ActualWidth, ElementName=Placeholder}"
              Y1="0" Y2="{Binding ActualHeight, ElementName=Placeholder}"
              StrokeThickness="2" Stroke="Blue"/>

Conclusion

I’m not saying the is the best, most efficient, or only way of doing this. However, it does mean that I can do it on both Windows Phone and Windows Store (and in WPF if I were so inclined) using a single shared project.

Reading NumPad keys using WinRT

Recently, I discovered a bug with one of my Windows Store games – Maths Races. The issue was that when a number key was pressed, the program works fine, but pressing a number pad key – even with NumLock on wasn’t recognised.

Here’s the code that I was using the detect the keypress:

KeyboardState newState = Keyboard.GetState();
var keys = newState.GetPressedKeys();

foreach (var key in keys)
{
    if (!IsNewKeyPressed(key))
        continue;

    byte keychar;
    if (byte.TryParse(key.GetHashCode().ToString(), out keychar))
    {
        char newChar = Convert.ToChar(keychar);

        if (Char.IsNumber(newChar))
        {
            . . . 

So, when I press a number pad key with Num Lock off, it behaves as though I’d pressed a different character; for example NumPad0 resolves to a key character code of 96:

(byte.TryParse(key.GetHashCode().ToString(), out keychar))

Which when converted to a char is “`”.

Okay, so here’s how I got around this:

if (key.HasFlag(Keys.NumPad0 & Keys.NumPad1 & Keys.NumPad2 &
    Keys.NumPad3 & Keys.NumPad4 & Keys.NumPad5 & Keys.NumPad6 &
    Keys.NumPad7 & Keys.NumPad8 & Keys.NumPad9))
{
    char number = key.ToString().Substring(6)[0];
    . . .
}                
else
   . . .

Admittedly it isn’t very pretty, and if someone knows a better, or more elegant way to do this, then please let me know.

MVVM Cross MvxStorePage Missing for 3.2.1

Recently I upgraded from MVVMCross 3.1.1 to 3.2.1 and everything broke. The reason was that suddenly, the MvxStorePage was unavailable.

After downloading the latest MVVMCross source, I found it safe and well:

namespace Cirrious.MvvmCross.WindowsStore.Views
{
    public abstract class MvxStorePage
        : Page
          , IMvxStoreView
    {

So – the page was still there in Cirrious.MvvmCross.WindowsStore.Views, but NuGet was no longer referencing its assembly:

Cirrious.MvvmCross.WindowsStore.dll

I posted this question.

And prompted by Stuart’s comments, I revisited the MVVMCross source. The confusing thing here is that the MvxStorePage has not been moved; it’s just been ignored and replaced by the MvxWindowsPage; here’s the new version:

namespace Cirrious.MvvmCross.WindowsCommon.Views
{
    public abstract class MvxWindowsPage
        : Page
          , IMvxWindowsView
    {

I’m sure many people knew this; but I wasn’t one of them.

Creating and Binding to a User Control in MVVM Cross

While creating my game, I recently came across the problem of navigation. This post describes how to create a custom user control and react to the event inside.

The usual disclaimer still applies here; although this is an MVVM Cross post, the contents of it should be applicable for any MVVM Framework or, in fact, any XAML binding at all.

User Control

The user control that I’m going to use is simply a navigation bar to appear at the top of each screen.

The XAML for the user control is here:

<UserControl
    x:Name="NavigationControlRoot">
    
    <Grid DataContext="{Binding ElementName=NavigationControlRoot}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Button Content="Home" Grid.Column="0" Command="{Binding HomeClick}" />
        <Button Content="Back" Grid.Column="1" Command="{Binding BackClick}" />
    </Grid>
</UserControl>

So, I’ve got two commands, binding to the code behind. The key point here is that the root control (grid) binds to the DataContext of the user control – effectively this binds it to the containing DataContext. Here’s the code behind:

    public sealed partial class NavigationPanel : UserControl
    {
        public static DependencyProperty BackCommandProperty =
            DependencyProperty.Register(
                "BackClick",
                typeof(ICommand),
                typeof(NavigationPanel),
                new PropertyMetadata(null));

        public static DependencyProperty HomeCommandProperty =
            DependencyProperty.Register(
                "HomeClick",
                typeof(ICommand),
                typeof(NavigationPanel),
                new PropertyMetadata(null));

        public NavigationPanel()
        {
            this.InitializeComponent();
        }
        
        public ICommand BackClick
        {
            get
            {
                return (ICommand)GetValue(BackCommandProperty);
            }

            set
            {
                SetValue(BackCommandProperty, value);
            }
        }

        public ICommand HomeClick
        {
            get
            {
                return (ICommand)GetValue(HomeCommandProperty);
            }

            set
            {
                SetValue(HomeCommandProperty, value);
            }
        }        
    }

So, you’ve now exposed two dependency properties and bound them to the XAML in the user control.

Host App

Here’s the relevant XAML for the hosting view:

<controls:NavigationPanel BackClick="{Binding BackClickCommand}"                                  
                                  HomeClick="{Binding HomeClickCommand}"/>

And that just binds to the ViewModel as you would expect.

        private IMvxCommand _homeClickCommand;
        public IMvxCommand HomeClickCommand
        {
            get
            {
                if (_homeClickCommand == null)
                {
                    _homeClickCommand = new MvxCommand(() => GoHome());
                }
                return _homeClickCommand;
            }
            set
            {
                _homeClickCommand = value;
            }
        }

        private void GoHome()
        {
            ShowViewModel<MainViewModel>();
        }

For me, this is in a base view model, so it responds to the same command in every view.

Conclusion

I think the final version of this code will interact with an IMvxPresenter in some way, which may make another post.

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.

MVVMCross – ShowViewModel not working?

I thought I’d jot this down, as it had me for a short while. Imagine that you have a line of code that looks like this:

ShowViewModel<MyViewModel>();

But nothing happens when you call it.

The Output Window

The output window is definitely your friend with MVVMCross; it may say something like this:

mvx:Diagnostic: 36.44 Error seen during navigation request to MyViewModel – error KeyNotFoundException: Could not find view for MyApp.PCL.ViewModels.MyViewModel
at Cirrious.MvvmCross.Views.MvxViewsContainer.GetViewType(Type viewModelType)
at Cirrious.MvvmCross.WindowsStore.Views.MvxStoreViewPresenter.Show(MvxViewModelRequest request)

So, what’s the problem?

Some things to check: firstly, check that you are using an MVVMCross view; that is, for example, in Windows 8, you need your page to inherit from MvxStorePage, not Page:

Conclusion

Nothing here that you won’t see on one of Stuart Lodge’s tutorials, and probably a good handful of SO questions. So now it’s here as well.