Remove Tap/Mouse Down Animations on GridView and ListView for Windows 8.1

Remove Tap/Mouse Down Animations on GridView and ListView for Windows 8.1

<disclaimer> The reason that the GridView and ListView have built-in animations for when a user taps or mouse-downs on an item is to provide feedback that they have indeed tapped/mouse downed on an item. I highly discourage the removal of these built-in animations as it will detract from your user experience. That said, there are times where you may need to remove these animations. For example if you nest a ListView within an item of a GridView, then, depending on what you want tappable, you’ll need to remove the animations on either the GridView or ListView.</disclaimer>

*If you’re building for Windows 8.0 then I suggest taking a look at some of the existing posts out there on how to remove storyboards from the ItemContainerStyle (eg http://stackoverflow.com/questions/10359197/windows-8-gridview-disabling-item-tap-visualization)

A lot of the discussion on the web is on how to remove various transitions from elements in Windows 8/8.1. For example setting the Transitions property to an empty TransitionsCollection. However, after setting virtually every transitions property I could find, I was still seeing the tap animation. It turns out that one solution is much simpler than I’d thought, and can be useful if you want to get rid on all the built in GridView/ListView item effects. Be warned, this will remove all those built-in effects!

Let’s walk through a simple example:

– Create a new Windows application based on the Hub App template – this will give us a GridView to work with. You can also use the Grid App if you want.

– Open the application in Blend (right-click the project and select “Open in Blend”)

– Locate a GridView to modify – we’re going to use the GridView in Section 3 of the Hub

– Right-click the GridView and select Edit Additional Templates –> Edit Generated Item Container (ItemContainerStyle) –> Edit a Copy

image

– Switch to code mode (I prefer split mode) and delete (or comment out) the GridViewItemPresenter element.

– Add an empty ContentPresenter element.

<Style x_Key=”GridViewItemStyle1″ TargetType=”GridViewItem”>
    <Setter Property=”FontFamily” Value=”{ThemeResource ContentControlThemeFontFamily}”/>
    <Setter Property=”FontSize” Value=”{ThemeResource ControlContentThemeFontSize}”/>
    <Setter Property=”Background” Value=”Transparent”/>
    <Setter Property=”TabNavigation” Value=”Local”/>
    <Setter Property=”IsHoldingEnabled” Value=”True”/>
    <Setter Property=”Margin” Value=”0,0,2,2″/>
    <Setter Property=”Template”>
        <Setter.Value>
            <ControlTemplate TargetType=”GridViewItem”>
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

– Run the application – you’ll notice that there is no tap animation on the GridView in section 3, yet it still responds to tap or mouse click on the item (just no visible feedback).

Note: If you have a GridView or ListView that isn’t interactive you can always either disable it or set the IsHitTestVisible property to false.

Taking Visual States Cross Platform to iOS and Android with Xamarin

Taking Visual States Cross Platform to iOS and Android with Xamarin

Last Friday at the Windows Phone 8.1 developer training, run by Microsoft, Nokia Microsoft and Built to Roam, we asked the room how many people used Blend and knew about Visual States. I was shattered to see very few people even knew what a Visual State was, let alone use them in their code. Visual States have to be one of the most useful aspects of the XAML system allowing you to define different states for not only your pages but also controls and user controls that you create.

On Tuesday night before the Sydney Mobile .NET Developer Meetup I was talking with Lewis Benge about how developers on other platforms control aspects of their user interface. The consensus is that it’s very reactive in that as elements of their data model, or in the case of mvvmcross elements of the view model, change elements of the UI are adjusted. For example if you were displaying some form of a loading indicator whilst some data was being retrieved from a service, when the call was complete, the progress indicator would be hidden. In this simple case you might think that it’s just one line of code to show or hide the progress indicator but now repeat this two or three times and all of a sudden you have UI control code littered throughout your application logic. In the XAML world we’d simply define these as visual states and we’d move between those states as required. In fact, as you’ll see we can even represent these states within our view model so that the state, not the visual representation of the states, form part of our application logic (and can be isolated and tested independently as it can sit nicely within a PCL).

Ok, now for a more concrete example:

– File –> New Project –> Windows Phone application

– Add New Project –> Android application

(you can repeat for iOS if you want)

– Add New Project – Portable Class Library

– Manage NuGet –> Add Mvvmcross to all projects, and follow “ToDos” as required for each project

>> At this point, you want to make sure that both your Windows Phone and Android applications build and can be run. They should both launch FirstView and contain a textbox and label with databinding working so that you can change the text in the textbox and it is updated in the label.

Blending some Visual States

We’re going to add a progress bar and a piece of text to say “Loading….” whilst data is being loaded.

– Right-click the Windows Phone project and select Open in Blend

– Add a progress bar and texblock to the contentpanel element to give you the following xaml – note that both elements are currently collapsed

<Grid x_Name="ContentPanel"
        Grid.Row="1"
        Margin="12,0,12,0">
    <ProgressBar x_Name="progressBar"
                    Visibility="Collapsed" />
    <TextBlock x_Name="textBlock"
                TextWrapping="Wrap"
                Text="Loading…"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Margin="0,-25,0,0"
                Visibility="Collapsed" />
</Grid>

– In the States tool windows, click the “Add state group” button in the icon bar. Call the state group “LoadingStates” (this name is somewhat irrelevant as it’s never used other than in Blend to allow you to differentiate if you have multiple state groups)

– Click the “Add state” button twice to generate states “Loading” and “Loaded”

– With the Loading state selected (there should be a red border around the main design surface indicating that you’re in state editing mode) set both textblock and progressbar to visible, and set the isindeterminate property to true. If you look at the xaml you should see the following states defined:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x_Name="LoadingStates">
        <VisualState x_Name="Loading">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                Storyboard.TargetName="progressBar">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ProgressBar.IsIndeterminate)"
                                                Storyboard.TargetName="progressBar">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <System:Boolean>True</System:Boolean>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                Storyboard.TargetName="textBlock">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
        <VisualState x_Name="Loaded" />
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

– If you switch between the Loading and Loaded states in Blend you should see the elements show and hide as expected. Now we need to wire up some logic to switch between these states at runtime.

– Return to Visual Studio and go to the code-behind file for the FirstView (Windows Phone project).

– Add the following code to the OnNavigatedTo method:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    VisualStateManager.GoToState(this, "Loading", true);
    await Task.Delay(2000);
    VisualStateManager.GoToState(this, "Loaded", true);
}

– Run the Windows Phone application and observe the application switching between the two states

– Now we need to move this logic one step further away from the UI layer and have it contained within our ViewModel. We’ll also try to eliminate those pesky string literals. To do this we’ll define an enumeration in code so that we can refer to our VisualStates – the name of the enumeration doesn’t matter but the name of the enumeration values needs to match the names of the states defined in Blend

public enum FirstStates
{
    Base,
    Loading,
    Loaded
}

– To move our state logic into the ViewModel we’ll need a way to trigger the actual state change in the UI layer (ie the view). For this we’ll expose an event on the ViewModel which will include the name of the state that we want the view to transition to. We’ll start by defining a StateEventsArgs class which we’ll use to wrap the name of the state. This class includes a couple of helper methods to make it easy to generate an instance from an enumeration value, and to return an enumeration value. You might ask why we’re converting to and from strings – we’ll come back to this!

public class StateEventArgs : EventArgs
{
    public string StateName { get; private set; }

    public static StateEventArgs Create<TState>(TState state) where TState : struct
    {
        return new StateEventArgs {StateName = state.ToString()};
    }

    public TState AsState<TState>() where TState : struct
    {
        TState state = default(TState);
        Enum.TryParse(StateName, true, out state);
        return state;
    }
}

– Update the FirstViewModel to raise a StateChanged event as follows:

public void OnStateChanged(FirstStates state)
{
    if (StateChanged != null)
    {
        StateChanged(this, StateEventArgs.Create(state));
    }
}
public override async void Start()
{
    base.Start();
    await Task.Yield(); // Attach state changed event handler

    OnStateChanged(FirstStates.Loading);
    await Task.Delay(5000);
    OnStateChanged(FirstStates.Loaded);
}
public event EventHandler<StateEventArgs> StateChanged;

– Now, in the code behind for our FirstView we can amend the OnNavigatedTo method to wire up a StateChanged event handler:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    (ViewModel as FirstViewModel).StateChanged += FirstView_StateChanged;
}

void FirstView_StateChanged(object sender, StateEventArgs e)
{
    VisualStateManager.GoToState(this, e.StateName, true);
}

– When you run this, there is a 5 second delay during the Start method in the FirstViewModel during which the Loading state should be visible. There after it should revert to the Loaded state.

– Let’s flip across to our Android project and amend the FirstView to include the following xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout >http://schemas.android.com/apk/res/android"
    >http://schemas.android.com/apk/res-auto"
    android_orientation="vertical"
    android_layout_width="fill_parent"
    android_layout_height="fill_parent">
    <EditText
        android_layout_width="fill_parent"
        android_layout_height="wrap_content"
        android_textSize="40dp"
        local_MvxBind="Text Hello" />
    <TextView
        android_layout_width="fill_parent"
        android_layout_height="wrap_content"
        android_textSize="40dp"
        local_MvxBind="Text Hello" />
    <Button
        android_id="@+id/MyButton"
        android_layout_width="fill_parent"
        android_layout_height="wrap_content"
        android_text="@string/Hello" />
    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_id="@+id/progressBar1" />
</LinearLayout>

– Note that unlike in XAML for Windows Phone we can’t define the visual states in xml. Instead we define them as a set of Actions which will be invoked when transitioning to a particular state. In this case we’re setting the progress bar to indeterminate and changing the button color for Loading state. You’ll notice that unlike in XAML where we could rely on the state manager to revert state changes (ie Loaded state simply reverses any changes applied by the Loading state), here we have to be explicit about all changes we want to occur.

private IDictionary<FirstStates, Action> states;
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.FirstView);

    var button = FindViewById<Button>(Resource.Id.MyButton);
    button.Click += (s,e) => ViewModel.Start();

    var progress = FindViewById<ProgressBar>(Resource.Id.progressBar1);

    states = new Dictionary<FirstStates, Action>()
    {
        {FirstStates.Loading, () =>
        {
            progress.Indeterminate = true;
            button.SetTextColor(new Color(0,255,0));
        }},
        {FirstStates.Loaded, () =>
        {
            progress.Indeterminate = false;
            button.SetTextColor(new Color(255,0,0));
        }}
    };
}

– The final piece is to wire up an event handler to the StateChanged event, the same as we did for Windows Phone:

protected override void OnViewModelSet()
{
    base.OnViewModelSet();

    (ViewModel as FirstViewModel).StateChanged += FirstView_StateChanged;
}

void FirstView_StateChanged(object sender, StateEventArgs e)
{
    var state = e.AsState<FirstStates>();
    var change = states[state];
    change();
}

– When the StateChanged event is trigger, we find the appropriate Action by looking in the state Dictionary. The Action is then invoked to apply the appropriate visual changes.

In this post I’ve walked you through the basics of how you can use visual states across both Android and Windows Phone, controlled from within your view models. This same model can be applied to iOS and of course the code for wiring up the state changed event can be abstracted into base view models and base views so you don’t need to add it to every page.

Using Universal Share Projects for Windows Phone Silverlight 8.0 and 8.1 Upgrade Path

Using Universal Share Projects for Windows Phone Silverlight 8.0 and 8.1 Upgrade Path

Of course with the announcement of Windows Phone 8.1 XAML applications (ie applications for WP8.1 written in Windows XAML) and support for Universal applications, not everyone is going to immediately rebuild their Windows Phone application. Instead, existing developers need a mechanism to upgrade to the new runtime to leverage the new features without having to redeveloper all their pages. This is where Silverlight 8.1 applications come in.

There is only minimal support within Visual Studio to support developers upgrading to Silverlight 8.1, allowing them to “Retarget to Windows Phone 8.1”.

image

Retargeting works well and typically your application will continue to run. However, in most cases you’ll want to maintain both a Silverlight 8.0 and 8.1 versions of your application. An alternative is to create a copy of your Silverlight 8.0 application and upgrade that – now you have two versions of your application that you have to support. Luckily this is an area where the new Shared project support, added to enable universal applications across Windows Phone and Windows, can be used to maintain code that is used by both a Silverlight 8.0 and 8.1 application (sort of Linked files on steroids).

Steps:

– Install the Shared Project Reference Manager (http://visualstudiogallery.msdn.microsoft.com/315c13a7-2787-4f57-bdf7-adae6ed54450) – this makes creating Shared Projects much easier

– Create a new Shared Project eg MyApplication.Shared

– Unload you Windows Phone project

– Edit your Windows Phone project file

– Add a Shared Project Reference via the right-click shortcut menu on your Windows Phone project (Note: for some reason adding a shared project reference isn’t supported for Windows Phone projects, so we need to do it the manual way)

– Add Import to end of project file which references the shared project file eg

<Import Project="..MyApplication.SharedMyApplication.Shared.projitems" Label="Shared" />

– Reload your Windows Phone project – you should see a reference to your Shared project under References node

image

– Move as many files as possible from your Windows Phone project into the Shared project

– Note that you may experience some of these issues:

> AppResources.resx doesn’t move easily. You’ll need to make sure that both the resx and the designer.cs file are moved and that the Build Action is correct (resx file should have a Build Action of Embedded Resource and a Custom Tool of PublicResXFileCodeGenerator). You also need to remove the “.Resources” from the name of the resource being loaded and the namespace.

> You need to keep any images referenced in the WMAppManifest.xml file in the Windows Phone project. This is ApplicationIcon.png and FlipCyleTileMedium.png by default

> You still need an App.xaml file in your Windows Phone project

– Check that your Windows Phone application builds and runs (fix any build errors!)

– In Windows Explorer take a copy of your Windows Phone application and rename the folder and project files eg MyApplication.SL81

– Add the copied project into the same solution

– Right click on the project you just added and select “Retarget to Windows Phone 8.1”. Your solution structure should now look similar to the following

image

– Build and run your new Windows Phone 8.1 application

The upshot after all this is that you have a Shared project where you can store shared files across your Windows Phone Silverlight 8.0 and 8.1 applications.

Sqlite for Universal Windows and Windows Phone applications

Sqlite for Universal Windows and Windows Phone applications

I hadn’t tested using Sqlite with the new universal projects introduced with Visual Studio 2013 Update 2 (which includes the Windows Phone 8.1 SDK). Luckily there is already quite a bit of info out there on the bits you need to get this to work.

  1. Firstly, you need a copy of the Sqlite Extensions library updated for WP8.1. At this point this hasn’t been officially release but Tim Heuer has posted a link to his “works on my computer” version of the library. His post is Using SQL/library references in Universal Windows Apps and includes a link to the extensions library
  2. The next thing to do is to create yourself a Universal project
  3. Add a reference to the sqlite extensions library to each of the head projects (ie the Windows and Windows Phone projects, not the shared project).
  4. Next, add a nuget reference to sqlite-net (use the package with that id)
  5. In the previous step you’d see sqlite.cs and sqliteasync.cs being added to both head projects. You can copy these files into the shared project and delete them from both head projects
  6. Lastly, add some sqlite code to your shared project which can then be used by both your Windows and Windows Phone projects…. simply done!

Here’s a sample project where I followed these steps