Thursday 18 July 2013

WP7 & WP8 XAP Windows Phone App

I've recently been having problems with an app that has a WP7 and WP8 package.

At first the package had the same version when submitted and WP8 devices correctly got the WP8 XAP and WP7 devices got the WP7 XAP.

Suddenly with no change, WP8 devices started getting the WP7 XAP.

We put in a ticket with the store team and the mentioned the versions had to be different, so I updated the WP8 package higher than the WP7 one and submitted it, in accordance with this guideline:

http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/15/app-submission-tips-for-windows-phone-7-and-windows-phone-8.aspx

This still did not help.

We asked support again and they examined the XAPs and started going on about one targeting 8.0 and one 7.1 AND 8.0. Well of course the 7 one will target both, because it's supposed to, but surely the store should be able to work it out?

We resubmitted a few times and nothing worked and we kept getting responses about the 7.1 and 8 thing.

Eventually I decided to up-version both XAPs with a minor fix together and that finally seemed to work!

Here's my check list for future reference:
  • Make sure the WP8 package has a higher version than the WP7 one in the WMAppManifest
  • Make sure the WP8 package has a higher version than the WP7 one on the store
  • Submit 2 XAPs at the same time

I've got another minor update to push out this week so will see if it works again!

Wednesday 10 July 2013

Windows 8 MVVM Drag Drop

Overview

I’ve recently added drag/drop functionality to a Windows 8 app between a GridView and a ListBox using an MVVM pattern. I created two Attached Properties to collect the dragged items and fire a command when they were dropped. Both work on ListViewBase controls.

DragItemStarting Attached Property


This detects the DragItemsStarting event on the source control and pushes the items into a bound IList<T> in the view model:

public class DragItemsStarting
{
    public static readonly DependencyProperty ItemsProperty =
            DependencyProperty.RegisterAttached("Items", typeof(IList<object>), typeof(DragItemsStarting), new PropertyMetadata(null, ItemsPropertyChanged));

    public static void SetItems(DependencyObject attached, IList<object> value)
    {
        attached.SetValue(ItemsProperty, value);
    }

    public static IList<object> GetItems(DependencyObject attached)
    {
        return (IList<object>)attached.GetValue(ItemsProperty);
    }

    private static void ItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Attach click handler
        (d as ListViewBase).DragItemsStarting += DragItemstarting_DragItemsStarting;
    }
             
    static void DragItemstarting_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
    {
        // Set Items
        SetItems(sender as DependencyObject, e.Items);
    }
}

DragItem Binding XAML


<GridView
    x:Name="pallette"
    cmd:DragItemsStarting.Items="{Binding DragObjects, Mode=TwoWay}"

DragItem Binding View Model

public IList<object> DragObjects
{
    get { return this._dragObjects; }
    set { this._dragObjects= value; }
}

Be careful to implement the getter and not return null as the attached property won’t attach if the value doesn’t change.

DropCommand Attached Property

This detects the drop event and fires the bound command. In my implementation, I wanted the pointer location so I passed that into the command:

public class DropCommand
{
    public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(DropCommand), new PropertyMetadata(null, CommandPropertyChanged));

    public static void SetCommand(DependencyObject attached, ICommand value)
    {
        attached.SetValue(CommandProperty, value);
    }

    public static ICommand GetCommand(DependencyObject attached)
    {
        return (ICommand)attached.GetValue(CommandProperty);
    }

    private static void CommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Attach click handler
        (d as FrameworkElement).Drop += DropCommand_Drop;
    }

    private static void DropCommand_Drop(object sender, DragEventArgs e)
    {
        e.Handled = true;

        // Get element
        var fe = (sender as FrameworkElement);

        // Get command
        ICommand command = GetCommand(fe);

        // Get pointer point
        var p = Window.Current.CoreWindow.PointerPosition;

        Debug.WriteLine(string.Format("DROP X: {0}, Y: {1}", p.X, p.Y));

        // Execute command
        command.Execute(p);
    }
}

DropCommand Binding XAML


<ListBox cmd:DropCommand.Command="{Binding DropCommand}"

DropCommand Binding View Model


public ICommand DropCommand
{
    get { return this._dropCommand; }
}

I usually have a method called by the constructor that created the commands:

this._dropCommand = new DelegateCommand(a =>
    {
        if (a is Windows.Foundation.Point)
        {
            this.DoSomething((Windows.Foundation.Point)a);
        }
       
    }, p => this.IsDropExecutable);

You can use any type of command; I've used Delegate command taken from the Prism framework. 

Conclusion

This provides a nice clean way of implementing drag and drop using an MVVM pattern.