Saturday, October 21, 2017

UWP Tip #8 - UWP Community Toolkit - Part 6, Using the VisualTree and LogicalTree UI Helpers

Welcome back to the UWP Community Toolkit series. Previous Tips in the UWP Community Toolkit series:
Introduction
This tip will continue exploring the Code Helpers that we started looking at in Part 3. There are only a few types of helpers remaining, and today we will examine the collection of available VisualTree and LogicalTree UI extension methods.
VisualTree Extensions
The VisualTree extension methods extend and simplify the built-in UI element navigation methods of the framework. There are currently five methods available to use in the toolkit.
  • FindDescendantByName(elementName) - Navigates down the visual tree until an element with the provided name is found.
  • FindDescendant<T>() - Navigates down the visual tree and returns the first element for the given type.
  • FindDescendants<T>() - Returns an IEnumerable of all descendant elements of the given type.
  • FindAscendantByName(elementName) - Navigates up the visual tree until an element with the provided name is found.
  • FindAscendant<T>() - Navigates up the visual tree and returns the first element for the given type.
Here is an example of the use of each method to retrieve UI elements from your visual tree.
public void ProcessVisualUiElements()
{
    var listControl = mainGrid.FindDescendantByName("resultList");
    listControl = mainGrid.FindDescendant<ListView>();
    listControl.MaxWidth = 500;
    foreach (var item in mainGrid.FindDescendants<ListViewItem>())
    {
        item.IsEnabled = false;
    }
    var gridControl = resultList.FindAscendantByName("mainGrid");
    gridControl = resultList.FindAscendant<Grid>();
    gridControl.Margin = new Thickness() { Bottom = 2, Left = 2, Right = 2, Top = 4 };
}

Most UWP developers will probably use the FindAscendant/FindDescendant methods using the type of element to find as we try to avoid naming our UI elements.
LogicalTree Extensions
The LogicalTree extensions are very similar but they operate over logical elements, ignoring certain containers and style elements only found in the visual tree. Not having to rely on knowing if the elements have been rendered yet before finding them can be an advantage of this method also.
The set of methods available mirror those for the visual tree with one additional method to find an element's content control.
  • FindChildByName(elementName)
  • FindChild<T>()
  • FindChildren<T>()
  • FindParentByName(elementName)
  • FindParent<T>()
  • GetContentControl()
The sample code also mirrors the previous sample.
public void ProcessLogicalUiElements()
{
    var listControl = mainGrid.FindChildByName("resultList");
   
    listControl = mainGrid.FindChild<ListView>();
   
    foreach (var item in resultList.FindChildren<ListViewItem>())
    {
        item.IsEnabled = true;
    }
   
    var gridControl = resultList.FindParentByName("mainGrid");
   
    gridControl = resultList.FindParent<Grid>();
   
    var searchContent = searchTextBox.GetContentControl();
}

Wrap-Up
That's all for today's helpers! They're very straightforward to use and can save quite a bit of manually traversing the visual and logical trees to find a target element. Check back as next time we will finish up the helpers provided by the UWP Community Toolkit.
Happy coding!

del.icio.us Tags: ,,








Thursday, October 12, 2017

UWP News - UWP in FCU Supports .NET Standard 2.0

Big news this week for UWP developers. If your app is targeting Windows 10.0.16299 (the Fall Creators Update), you can now access ~20,000 APIs that were added as part of .NET Standard 2.0.

The announcement was made during Windows Developer Day on Tuesday, and a .NET Blog post by Rich Lander and Immo Landwerth dives into some of the details.

In order to use .NET Standard 2.0 in UWP, you need to target Fall Creators Update (FCU) as the minimum version of your UWP project. That’s because .NET Standard 2.0 contains many APIs that require FCU to make them work in the context of the UWP execution environment, specifically AppContainer.

To get started, go upgrade to the Fall Creators Update, get the new Windows SDK and the new build of Visual Studio 2017 (v15.4). Get started building new UWP apps or updating your existing apps to support the FCU features and .NET Standard 2.0. Microsoft is offering some great prizes in a new contest to encourage Windows developers to target the FCU, including a Surface Studio. Get the contest details here.

Landwerth has also updated his .NET Standard Selector website to include .NET Standard and UWP. If you are unsure of which platforms are supported by each version of .NET Standard, check out this handy reference.

Happy coding!

Friday, September 29, 2017

UWP Tip #7 - UWP Community Toolkit - Part 5, Using the Streams Code Helper

Welcome back to the UWP Community Toolkit series. Previous Tips in the UWP Community Toolkit series:

Introduction

This tip will continue exploring the Code Helpers that we started looking at in Part 3. There are three types of helpers remaining, and today we will examine the StreamHelper class.

Purpose

The StreamHelper class contains methods to read files from a stream via local files or via a network stream. There is also a helper method to read data from an http source and write it directly to a local file. There are also some helper methods to check if files and folders exist for a given name and path.

Let's look at a few of the method signatures:

  • GetHttpStreamAsync(System.Uri uri) - Gets a stream from an HTTP request.
  • IsLocalFileExistsAsync(System.String fileName) - Checks if a local files exists in the application's folder.
  • IsLocalCacheFileExistsAsync(System.String fileName) - Checks if a local file exists in the cache folder.
  • ReadTextAsync(Windows.Storage.Streams.IRandomAccessStream stream,System.Text.Encoding encoding) - Takes a stream and reads it to a returned string.

Example

In this short example, we are going to create a StreamService for our project that implements an IStreamService interface for testability. Although the lack of an interface for the toolkit's StreamHelper makes it a little tricky to mock this for our tests. We'll leave this for another day or perhaps an issue to be filed on their GitHub.

The StreamService has two methods, one for getting a string back from and HTTP call and another to get one from reading a file in the local cache.

public class StreamService : IStreamService
{
    public async Task<string> GetStringFromUrlAsync(Uri source)
    {
        using (var stream = await StreamHelper.GetHttpStreamAsync(source))
        {
            return await stream.ReadTextAsync();
        }
    }
     public async Task<string> GetStringFromLocalCacheAsync(string fileName)
    {
        using (var stream = await StreamHelper.GetLocalCacheFileStreamAsync(fileName, Windows.Storage.FileAccessMode.Read))
        {
            return await stream.ReadTextAsync();
         }
    }
}

Everything is wrapped up with only strings and a Uri in and out, keeping the external dependency out of our ViewModels. To check out all of the available helper methods in the StreamHelper class, you can visit the API documentation here.

Wrap-Up

Only two helper types to go. Next time we will continue with the VisualTreeExtensions code helper in the UWP Community Toolkit.

Happy coding!

 

del.icio.us Tags: ,

Tuesday, September 26, 2017

UWP App Tips Recommended Video - Bringing Your WinForms/WPF Investments Forwards with UWP/.NET Standard 2.0

The UWP Community Toolkit tips series will continue later this week. Today's post is a video that I recommend to all Windows developers.

Last week, Microsoft's Channel 9 hosted the online virtual 3-day conference, .NET Conf. The conference covered topics ranging from ASP.NET Core to Xamarin to Visual Studio tooling and lots more. I recommend you go check out all of the sessions to see what interests you. Last I checked, there were 45 videos available for the conference.

The one video I wanted to call out for UWP and all other Windows developers is titled Bringing Your WinForms/WPF Investments Forwards with UWP/.NET Standard 2.0. This session was presented by Chris Barker and Daniel Jacobson is described as:

.NET Standard 2.0 with Visual Studio 2017 makes it even easier to bring your WinForms/WPF investments to the Universal Windows Platform - enabling you to reach new audiences and easily deliver a modern user experience, all whilst continuing to service your existing user base. This session will introduce you to the benefits of .NET Standard 2.0, and walk you through the process for extending the reach of your app efficiently.
The hosts are very engaging and I think this session is yet another indicator that Microsoft is standing firm on their position that UWP is the way forward for all Windows app development.While large legacy code bases on WinForms and WPF may not ever migrate to UWP. I work for a company with a mix of WPF, WinForms and MFC which is unlikely to take this path. However, it is a real possibility for many WPF and some WinForms applications, especially those which are smaller non-enterprise applications.

Enjoy the video and don't forget to peruse the rest of them on Channel 9!


Friday, September 22, 2017

UWP Tip #6 - UWP Community Toolkit - Part 4, Leveraging the StorageFiles and Storage Code Helpers

Welcome back to the UWP Community Toolkit series. You'll have to excuse the delay between posts as TechBash 2017 has been monopolizing my free time this month.

Previous Tips in the UWP Community Toolkit series:

Introduction

This tip will continue exploring the Code Helpers that we started looking at in Part 3. There are five types of helpers remaining, and today we'll look at the StorageFileHelper and Storage helpers.

StorageFiles

The StorageFileHelper utility class has helper methods for reading from and writing to disk. There are method overloads to read and write both text and binary data to a file either directly to the local storage folder or to given folderId and/or folderName. Some overloads for writing take a CreationCollisionOptions parameter to decide how to handle conflicts during file or folder creation. All StorageFile operations are async.

Here is a simple example of simple read and write service methods that wrap calls to the StorageFileHelper methods that use the user's local storage.

 public async Task WriteUserData(string data, string fileName)
{
    await StorageFileHelper.WriteTextToLocalFileAsync(data, fileName);
}

public async Task<string> ReadUserData(string fileName)
{
    return await StorageFileHelper.ReadTextFromLocalFileAsync(fileName);
}

Storage

The StorageService, not to be confused with the previous StorageFileHelper, is for reading and writing objects within your application. The objects can be read and written locally or you can choose to roam the data across all the user's devices. This selection is made by using either a LocalObjectStorageHelper or a RoamingObjectStorageHelper. Makes sense.

Let's say you had a health care application of some kind and you wanted to save an object containing the currently selected clinic's information.

 public class Clinic : IClinic
{
    public string Name { get; set; }
    public string Location { get; set; }
    public int NumberOfBeds { get; set; }
    public ClinicType Type { get; set; }
}

We want to take this and persist it for the current device. So, we'll create some service methods to read and write the object local to the current device.

    public class StorageService
    {
        private LocalObjectStorageHelper _localStorageHelper = new LocalObjectStorageHelper();

        public async Task SaveClinic(IClinic clinic, string key)
        {
            await _localStorageHelper.SaveFileAsync(key, clinic);
        }

        public async Task<IClinic> ReadClinic(string key)
        {
            return await _localStorageHelper.ReadFileAsync<IClinic>(key);
        }
    }

That's it. We've wrapped the methods to read and write and only need to deal with our own interfaces in and out. If you wrap this service class in an interface and inject the helper itself, it will be nicely abstracted for testability. You can use these service methods from any of the existing ViewModels in your UWP app.

Wrap-Up

Next time we will continue with the Code Helpers in the UWP Community Toolkit. The Streams helper is up next.

Happy coding!