Visually Located

XAML and GIS

Setting the device wallpaper in Windows Universal Apps

Windows 10 launched today and with it comes a new SDK for building “Universal Apps”. This new SDK comes with a lot of new functionality. One of those pieces is a new way to set the wallpaper of a device. This new API is available on the new UserProfilePersonalizationSettings class. This class is used for setting the lockscreen, and the device wallpaper. The new UserProfilePersonalizationSettings class has a TrySetWallpaperImageAsync method that accepts any local StorageFile (I have not been able to set the wallpaper using the FileOpenPicker). This means you can save an image to the local or roaming folders, or use an existing image packaged with your app.

var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AwesomeWallpaper.jpg"));
await Windows.System.UserProfile.UserProfilePersonalizationSettings.Current.TrySetWallpaperImageAsync(file);

This example uses a file packaged with the app in the Assets folder.

image

You should check if the device has the ability to change the wallpaper. I’m guessing this is in place for future Windows settings.

if (Windows.System.UserProfile.UserProfilePersonalizationSettings.IsSupported())
{
    var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AwesomeWallpaper.jpg"));
    await UserProfilePersonalizationSettings.Current.TrySetWallpaperImageAsync(file);
}

Now go and create some amazing wallpaper apps for Windows 10

Setting the lockscreen in Windows Universal Apps

Windows 10 launched today and with it comes a new SDK for building “Universal Apps”. This new SDK comes with a lot of new functionality. One of those pieces is a new way to set the lockscreen of a device. This new API is available on the new UserProfilePersonalizationSettings class. Previously you only had the ability to set the lockscreen within phone apps using the SetImageUri method on the static LockScreen class. The method accepted a Uri that had to be local to the app.

Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri(localFileName));

The new UserProfilePersonalizationSettings class has a TrySetLockScreenImageAsync method that accepts any local StorageFile (I have not been able to set the lockscreen using the FileOpenPicker). This means you can save an image to the local or roaming folders, or use an existing image packaged with your app.

var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AwesomeLockscreen.jpg"));
await Windows.System.UserProfile.UserProfilePersonalizationSettings.Current.TrySetLockScreenImageAsync(file);

This example uses a file packaged with the app in the Assets folder.

image

You should check if the device has the ability to change the lockscreen. I’m guessing this is in place for future Windows settings.

if (Windows.System.UserProfile.UserProfilePersonalizationSettings.IsSupported())
{
    var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/AwesomeLockscreen.jpg"));
    await UserProfilePersonalizationSettings.Current.TrySetLockScreenImageAsync(file);
}

Now go and create some amazing lockscreen apps for Windows 10

Persist ListView scroll position without setting NavigationCacheMode

In a previous post I wrote about why your ListView resets to the top of the list when navigating backwards. In that post I looked at using the NavigationCacheMode of the page to persist the scroll position of your ListView. I also briefly mentioned using the ScrollIntoView method of the ListView. In this post we’ll look at a little known helper class that allows you to keep your scroll position without using all the memory that NavigationCacheMode can use.

ListViewPersistenceHelper

The ListViewPersistenceHelper class allows you to easily restore the scroll position with only two methods, GetRelativeScrollPosition and SetRelativeScrollPositionAsync. These methods use the item that is at the top of the list as indicators for where the scroll position should be.

The GetRelativeScrollPosition should be called when navigating away from the page. A good place is the OnNavigatedFrom method.

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    _positionKey = ListViewPersistenceHelper.GetRelativeScrollPosition(myListView, ItemToKeyHandler);
    base.OnNavigatedFrom(e);
}
 
private string ItemToKeyHandler(object item)
{
    MyDataItem dataItem = item as MyDataItem;
    if (dataItem == null) return null;
 
    return dataItem.Id;
}

The SetRelativeScrollPositionAsync method tells the ListView where to scroll to. A good place to call this method is in the OnNavigatedTo method.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if (_positionKey == null) return;
 
    ListViewPersistenceHelper.SetRelativeScrollPositionAsync(myListView, _positionKey, KeyToItemHandler);
}
 
private IAsyncOperation<object> KeyToItemHandler(string key)
{
    Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<object>> taskProvider = token =>
    {
        var viewModel = DataContext as MyViewModel;
        if (viewModel == null) return null;
        foreach (var item in viewModel.Items)
        {
            if (item.Id == key) return Task.FromResult(item as object);
        }
        return Task.FromResult((object)null);
    };
 
    return AsyncInfo.Run(taskProvider);
}

In this simple example I’m storing the _positionKey key in a static field. This is ok for a simple case, but you may want to store this somewhere else.

Precautions:

I did notice that if you are animating the items of your ListView and using the ListViewPersistenceHelper, that there are some unintended side effects. The first few items of your ListView will still show the animation when navigating backward while the other items remain still. You can see this in the image below.

Animating side-effect

A simple work around for this is to reset the ItemContainerTransitions of the ListView in the OnNavigatedTo method if the _positionKey is not null.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    if (_positionKey == null) return;  
 
    myListView.ItemContainerTransitions = new TransitionCollection();
    ListViewPersistenceHelper.SetRelativeScrollPositionAsync(itemListView, _positionKey, KeyToItemHandler);
}

Hopefully this will help your apps use less memory while still maintaining a great experience for your users!

Easily create Microsoft Band Web Tiles with the Web Tiles Authoring website

The Microsoft Band team released “Web Tiles” today. Web Tiles are a simple way to show tiles on your Microsoft Band without needing to write an app. The tiles update from a web url. As far as I can tell, the web url must return json data. This data can be whatever but it needs to be open to everyone meaning no authentication. All of the articles today talk about the structure of a web tile and what each piece means. All this information is great, but if you only need a simple tile you can do without it.

Along with the release of Web Tiles, Microsoft also released a Web Tiles Authoring website. This website walks you through creating a new tile step by step. Let’s take a look at how this works

Step 1: Choose a layout

Here you pick which of the six layouts you’d like to use for the tile. You can choose from displaying a single page tile or multiple page tile. Multiple page tiles must link to an RSS or ATOM feed. This is not a requirement of web tiles; it is only a requirement for the authoring tool. Web tiles can have multiple pages without needing an ATOM or RSS feed.

Choose a layout

Step 2: Assign the url

Here you enter the url that will contain the data for your tile. If you picked a multiple page layout from Step 1, you must enter a URL for RSS or an ATOM feed. Again, this is not a requirement for web tiles, only for the authoring tool.

Assign the url

Step 3: Selecting information to display

Here you select what information from your json feed you would like to display. You simply drag the data from the right and drop it onto the place you’d like to display it.

Select information-a     Select information-b

Here we see that I selected to display the weather with the state being the header, the second line being the temp and the third line being some description.

Step 4: Make it yours

Here you’ll set the information to make the tile yours.

 Make it yours

Step 5: Download!

Download this awesome web tile to send to your favorite people

download

Hopefully the tool will be improved to allow for multiple pages when your resource is not an ATOM or RSS feed.

A simpler FilePicker for Windows Phone and Windows apps

If you’ve built a Windows Phone app that uses the FileOpenPicker you know that it can be a pain while the Windows variation is pretty simple to use. In Windows you use the PickSingleFileAsync method and continue code as you think you would.

StorageFile storageFile = await openPicker.PickSingleFileAsync();
// Do something with the file

However in Windows Phone this becomes a little more complex. It’s especially complex when you look at the sample on MSDN. First you call the PickSingleFileAndContinue method, then in App.xaml.cs wait for the app to be activated, then somehow get back to where you were before. It’s a mess. I wanted to make this easier in a recent app I was working on and I wanted it to work the same for Windows and Windows Phone.

To get started you’ll need to know that the CoreApplicationView can give us access to when the app is activated. With this, we can bypass all the weirdness of using the App class.

CoreApplication.GetCurrentView().Activated += OnViewActivated
...
...
private async void OnViewActivated(CoreApplicationView sender, IActivatedEventArgs args)
{
    sender.Activated -= OnViewActivated;
    // do some stuff
}

Let’s create a new Picker that will get any image files. We’ll create a new ImagePicker class. This class will be a shared class between Windows and Windows Phone apps. Let’s stub that out now.

public class ImagePicker
{
    public Task<IRandomAccessStream> PickAsync()
    {
        // TODO: this
    }
}

Pretty simple class, right? Let’s fill in the pieces. We’ll still use the FileOpenPicker within the PickAsync method. This is an ImagePicker so we want to state that it needs to look for images

public Task<IRandomAccessStream> PickAsync()
{
    FileOpenPicker openPicker = new FileOpenPicker();
    openPicker.ViewMode = PickerViewMode.Thumbnail;
    openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    openPicker.FileTypeFilter.Add(".jpg");
    openPicker.FileTypeFilter.Add(".jpeg");
    openPicker.FileTypeFilter.Add(".png");
 
    // TODO: the rest
}

At this point we need to break up into Windows Phone code and Windows code

private TaskCompletionSource<IRandomAccessStream> _imageCompletionSource;
 
#if WINDOWS_PHONE_APP
public Task<IRandomAccessStream> PickAsync()
#else
public async Task<IRandomAccessStream> PickAsync()
#endif
{
    FileOpenPicker openPicker = new FileOpenPicker();
    openPicker.ViewMode = PickerViewMode.Thumbnail;
    openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
    openPicker.FileTypeFilter.Add(".jpg");
    openPicker.FileTypeFilter.Add(".jpeg");
    openPicker.FileTypeFilter.Add(".png");
 
#if WINDOWS_PHONE_APP
    _imageCompletionSource = new TaskCompletionSource<IRandomAccessStream>();
    CoreApplication.GetCurrentView().Activated += OnViewActivated;
    openPicker.PickSingleFileAndContinue();
    return _imageCompletionSource.Task;
#else
    StorageFile storageFile = await openPicker.PickSingleFileAsync();
    return await storageFile.OpenAsync(FileAccessMode.Read);
#endif
}

Notice for Windows Phone we will use a TaskCompletionSource to return the value. The result for the TaskCompletionSource will be set in the OnViewActivated method.

private async void OnViewActivated(CoreApplicationView sender, IActivatedEventArgs args)
{
    sender.Activated -= OnViewActivated;
    FileOpenPickerContinuationEventArgs pickerArgs = args as FileOpenPickerContinuationEventArgs;
 
    IRandomAccessStream stream = null;
    if (pickerArgs != null)
    {
        if (pickerArgs.Files.Count > 0)
        {
            StorageFile storageFile = pickerArgs.Files[0];
            stream = await storageFile.OpenAsync(FileAccessMode.Read);
        }
    }
    _imageCompletionSource.SetResult(stream);
}

Now with this simple class you can pick an image file like such

var picker = new ImagePicker();
var accessStream = await picker.PickAsync();

And that works the same for both Windows and Windows Phone. I did test this on a low memory device and it did work there as well!

You can find a “generic” version of this class here.