Sunday, August 6, 2017

UWP Tip #4 - UWP Community Toolkit - Part 2, Consuming the Services

Previous Tips in the UWP Community Toolkit series:
In this tip, we are going to look at the services provided by the UWP Community Toolkit. Currently, there are three services exposed through the toolkit:
  • Bing - Add Bing search capability to your Windows app.
  • Facebook - Read a user's Facebook data and post for them.
  • Twitter - Read, search and post on Twitter easily.
To get started with any of these services, add the "Microsoft.Toolkit.Uwp.Services" NuGet package to your UWP application in Visual Studio.

I created a simple app that can use Bing to do a regular search or news search and display the title, summary and url of the search results in a ListView with minimal formatting. The user can then select one of the results and tweet the title + url to their followers.

The app uses The UWP Community Toolkit for services and MVVMLight to add MVVM capabilities. Let's start by taking a look at the two services classes added to wrap the Toolkit's Bing and Twitter service calls.

public class SearchService : ISearchService
    public async Task<List<IQueryResult>> Search(string searchText, bool searchNews)
        var searchConfig = new BingSearchConfig
            Country = BingCountry.UnitedStates,
            Language = BingLanguage.English,
            Query = searchText,
            QueryType = searchNews ? BingQueryType.News : BingQueryType.Search
        var results = await BingService.Instance.RequestAsync(searchConfig, 50);         var queryResults = new List<IQueryResult>();
        foreach (var x in results)         {             queryResults.Add(new QueryResult             {                 Title = x.Title,                 Summary = x.Summary,                 Link = x.Link             });         }
        return queryResults;     } }
public class LocalTwitterService : ILocalTwitterService {     private string _key = "";  // removed (add your key here)     private string _secret = "";  // removed (add your secret here)     private string _callbackUri = "";  // removed (add your uri here)
    public async Task SendTweetAsync(string title, string url)     {         // Initialize service         TwitterService.Instance.Initialize(_key, _secret, _callbackUri);
        // Login to Twitter         if (!await TwitterService.Instance.LoginAsync())         {             return;         }                 // Post a tweet         await TwitterService.Instance.TweetStatusAsync($"shared: {title} {url}");     } }

The services are consumed in the MainViewModel after being injected into the VM's constructor. There are Search and Tweet It buttons on the UI which invoke each command method in the VM.

public ICommand SearchCommand { get; private set; }
public ICommand SendTweetCommand { get; private set; }
public async void Search() {     SelectedResult = null;     RaisePropertyChanged(nameof(SelectedResult));
    var results = await _searchService.Search(SearchText, SearchNews);
    foreach (var result in results)     {         QueryResults.Add(result);     } }
public async void SendTweet() {     await _twitterService.SendTweetAsync(SelectedResult.Title, SelectedResult.Link); }

The SearchText property contains the search terms entered by the user and SearchNews is a boolean property bound to a checkbox on the UI. QueryResults is an ObservableCollection of IQueryResult, a class holding the Title, Summary and Link of each search result, and SelectedResult is bound to the SelectedItem on the ListView.

The view for the main page consists of a Grid with three rows and three columns and these contents:

<TextBox Grid.Column="0" Margin="4" Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="1" Content="Search" Margin="0,4,0,4" Command="{Binding SearchCommand}"/>
<CheckBox Content="Search News" Grid.Column="2" IsChecked="{Binding SearchNews, Mode=TwoWay}"/>
<ListView Grid.Row="1" Grid.ColumnSpan="3" Margin="4"             ItemsSource="{Binding QueryResults}"             SelectedItem="{Binding SelectedResult, Mode=TwoWay}">     <ListView.ItemTemplate>         <DataTemplate>             <Grid Margin="4">                 <StackPanel VerticalAlignment="Top">                     <TextBlock Text="{Binding Title}"/>                     <TextBlock Text="{Binding Summary}" TextWrapping="Wrap"/>                     <TextBlock Text="{Binding Link}"/>                 </StackPanel>             </Grid>         </DataTemplate>     </ListView.ItemTemplate> </ListView>
<Button Grid.Row="2" Grid.Column="2" Content="Tweet It!"         Margin="4" HorizontalAlignment="Stretch"         Command="{Binding SendTweetCommand}"/>

Here is a look at the running application with one of the search results selected and ready to tweet.

The entire application consists of very little code, and could contain even less if you were content to wire up events directly in the main view's code behind without any service classes wrapping the Toolkit services or ViewModels abstracting logic from the UI. I feel it is best to practice writing decoupled, testable code even in the simplest of sample applications.

Go check out the latest drop of the UWP Community Toolkit online or via NuGet today. Happy coding!

No comments:

Post a Comment