Alessandro Del Sole's Blog

/* A programming space about Microsoft® .NET® */
posts - 159, comments - 0, trackbacks - 0

My Links

News

Your host

This is me! This space is about Microsoft® .NET® and Microsoft® Visual Basic development. Enjoy! :-)

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.

Microsoft MVP

My MVP Profile

I'm a VB!

Watch my interview in Seattle

My new book on VB 2015!

Pre-order VB 2015 Unleashed Pre-order my new book "Visual Basic 2015 Unleashed". Click for more info!

My new book on LightSwitch!

Visual Studio LightSwitch Unleashed My book "Visual Studio LightSwitch Unleashed" is available. Click the cover!

Your visits

Follow me on Twitter!

CodePlex download Download my open-source projects from CodePlex!

Article Categories

Archives

Post Categories

.NET Framework

Blogroll

Help Authoring

Microsoft & MSDN

Setup & Deployment

Visual Basic 2005/2008/2010

mercoledì 26 ottobre 2016

Visual Studio Code: version control with Visual Studio Team Services (Windows and Mac)

As you know, Visual Studio Code is extremely useful and versatile. It is a cross-platform development tool that I've personally described with my ebook Visual Studio Code Succinctly.

Among its various characteristics that make it a development tool rather than a mere editor, there is the native integration with Git, the popular version control engine which is also open source and cross-platform. In the ebook I explain how to integrate Code with GitHub, in this post I will explain how to integrate Visual Studio Code with Git repositories on Visual Studio Team Services, with Windows and Mac. Of course everything I'll describe applies to Linux as well.

Prerequisites
You need a few prerequisites:
  • Visual Studio Code
  • A Visual Studio Team Services account. Remember you can get one for free, up to 5 members in the team
  • Git.You should already have it if you installed  Visual Studio 2015. On Mac, you should already have it if you installed XCode. If not, follow the instructions in the download page for all the supported operating systems
  • .NET Core and the CLI.
Objectives
We'll reach two objectives: the first is adding a .NET Core project to an online repository, while the second one is cloning an existing VSTS repository.

Creating a repository with Visual Studio Team Services

I assume that you have created your account and you entered the website, normally available at username.visualstudio.com. In the home page you will find a link to create a new Team Project, just as you would for the TFS engine. When ready, type a name for the team project, an optional description and make sure Git is selected as the source control engine




After clicking Create project, you will see a welcome page. Click on Add some code at this point. You will be offered an option to clone the repository by using Visual Studio, but we don't care. You will be provided the URL of the repository, and you will need to specify the credentials associated with Git. The URL of the repository will be used in a little while, so copy it somewhere or in memory. Although you can specify a user name and password, it is best to generate a token. This will be useful later in Visual Studio Code. That said, click on Create a personal access token (if you have one already, you can skip this step):




In the token creation page you will need to specify a friendly name, expiration and the associated account. The latter is necessary because your email address may be associated with more than one account on VSTS. Choose the account where you set up the Git repository. When you create the token, make sure you have selected the permissions as shown in the following figure:



It is worth noting the Work items permission: this will make you understand that you have an option to manage work items such a pull requests. After clicking Create Token, the token will be shown and can be copied. Important: copy the token in a secure place and keep it safe; do not lose it because this is the only time you will see it. It will be used in a couple minutes.

Creating a sample project

The configuration of the Git repository with VS Code is the same with any folder Code itself can handle, but for the sake of convenience we'll see the steps with a .NET Core project. Open a command prompt inside the folder in which you want to create the project, then type the following line:

> dotnet new -t web

This will create a new ASP.NET Core project in C#. Next, open the newly created project with Visual Studio Code. At startup, it will require your permission to create some missing assets and to restore missing NuGet packages. Of course, give your permission to both.

Configuring Visual Studio Code

The steps I'm going to describe are the same on Mac and Linux, I'm using Windows in this case. In order to make Code able to connect with Visual Studio Team Services, you must install the same-named free extension provided by Microsoft:



In my case the extension is already installed, this is why the Install button is disabled. Once installed and Code ha restarted, click the Git icon from the panel at the left, then click Initialize Git repository. This is a mandatory step, because Git first works with a local repository and then with a remote one. At this point, perform a local commit:



Now that you have configured a local repository and that the project is associated to it, it is also necessary to associate the remote repository. Open a command prompt on the folder that contains the project and type the following:

> git remote add origin https://accountname.visualstudio.com/_git/repositoryname
> git push -u origin master

In the first line, of couse replace accountname with your actual account name and repositoryname with the name of your repository. The second line pushes the source code to the master branch of the local repository, and finalizes the association between the project and the remote repository.

Go back to Visual Studio Code. What you should do now is to map the environment with the remote repository. Actually it is easily done. You have two alternatives: click the Team icon in the status bar at the bottom left, or type Team login in the Command Palette. In the first case you will see this error:



If you click Close, you will be required to enter the token you created previously within Visual Studio Team Services:



At this point you will be authenticated and Visual Studio Code will automatically recognize that the local repository has a related remote repository, as demonstrated in the status bar where you can see the name of the repository, plus a number of icons that you can use to manage branches and pull requests (I won't cover this in this post):



You will see a sync button near the name of the current branch. Before syncing, you need to perform a commit because the association of the remote repository has caused Code to generate a couple of additional files. Once committed, click the Sync icon. After a few seconds you should be able to see your code in the Visual Studio Team Services portal:



Now you are ready to work in team on the project. Obviously, other people working on the project must clone the repository. This is described in the next section and applies to both existing and new repositories.

Cloning the repository (Mac edition)

I'll be describing how to clone a remote Git repository from Visual Studio Team Services to Visual Studio Code using a Mac. This is identical on Windows and Linux too. On the Mac, create a new folder where you will want to clone the repository and open an instance of the Terminal on that folder. Then type the following line:

> git clone https://accountname.visualstudio.com/_git/repositoryname

replacing the account name and repository name. After a few seconds you will be required to enter your email address and password. The email address must be the same you used to create the remote repository. You might also want to consider Git credential managers (some are listed in the VSTS page for the repository). The password is instead the token created before. Note: Mac OS does not show any masked character when you type the password and you will see nothing: no worries, paste the token and press Enter:



Once the process is completed, you will be able to open the project in Visual Studio Code, which of course implies installing the Visual Studio Team Services extension and signing in with the token:



Commits you make will be sync'ed with the remote repository and other team members will be able to work on the project by simply clicking the sync icon.

Visual Studio Team Services is very powerful with all the advantages of the Cloud, so combining it with Visual Studio Code makes this even more appealing.

Alessandro

posted @ mercoledì 26 ottobre 2016 22:00 | Feedback (0) | Filed Under [ Visual Studio 2015 ]

martedì 18 ottobre 2016

Code Snippet Studio updated to version 1.4.1

I have just released a new version of Code Snippet Studio, more precisely version 1.4.1.

This version addresses an issue I received on GitHub that caused the extension to crash when attempting to convert a .vsi archive to a .vsix package. The reason was a NuGet package mismatch.

It also introduces two new features:

1. For C# code snippets, it allows you to select between Expansion and Surrounds With types. This is useful when you ask IntelliSense to surround a piece of code with a snippet or to place a snippet at the point where the cursor is. You can make this choice in the property grid.

2. Conversion of Sublime code snippets into Visual Studio code snippets. Note: this is a work-in-progress feature and it's not completed. It can import a snippet, detect the programming language, and parse some metadata information. What it does not yet is parsing string replacements into the so-called declaration. This will come in a future version and your contributions would be appreciated.

Remember that Studio is powered by another open source library of mine, DelSole.VSIX, so if you want to request features or provide your contributions I would prefer submissions to this library rather than to Code Snippet Studio.

Alessandro

posted @ martedì 18 ottobre 2016 17:31 | Feedback (0) | Filed Under [ Visual Studio 2015 ]

sabato 24 settembre 2016

Important updates about Code Snippet Studio

I have just updated Code Snippet Studio to version 1.3.9 with a couple major changes, both in the tool and in the project vision.

Feature updates

First, the new version includes an option to change the foreground color in the code editor, both in normal and selected state. You simply use the color pickers like this:



Here I have used the ColorPicker control from Syncfusion's Essential Studio for WPF, yet Community License. If you have installed version 1.3.8, you might have noticed the availability of a third picker to change the background color for text selection. In 1.3.9, I decided to remove this because it was unstable and required VS to be restarted, and it did not fit well with color selection with Roslyn analysis.

I have also updated themes according to the latest Theme controls in Essential Studio, where I decided to remove themes based on Visual Studio 2013 and Office 2013 and use the new Visual Studio 2015 and Office 2016 themes.

Project decisions

I have decided to maintain and update (on regular basis and based on the community feedback) only the extension for Visual Studio, which has reached more than 7500 downloads. This means I won't be updating or maintaining the stand-alone version anymore.

As usual, submit your comments and issues on GitHub.

Alessandro

posted @ sabato 24 settembre 2016 11:17 | Feedback (0) | Filed Under [ Visual Studio 2015 ]

sabato 17 settembre 2016

CrossAnalyzers, a new set of Roslyn refactorings and analyzers for VB and C#

I love open source and I recently published another project to GitHub called CrossAnalyzers.

This project provides a number of code analysis rules and refactorings for both Visual Basic and C#, that integrate into the Visual Studio 2015 code editor.

It's typically about patterns, e.g. it suggests you are binding a List instead of an ObservableCollection in platforms such as WPF or Xamarin, or it easily allows implementing view models or the INotifyPropertyChanged interface.

Analyzers are available on NuGet, while both analyzers and refactorings are also available in the Visual Studio Gallery. Here's a sample in action, but don't forget to check out the repository with more docs.



Alessandro

posted @ sabato 17 settembre 2016 12:18 | Feedback (0) | Filed Under [ Visual Studio 2015 .NET Compiler Platform (Roslyn) ]

Chatting about Code Snippet Studio with Syncfusion

Code Snippet Studio is an open source tool I started to build almost an year ago and, honestly, I mainly did it for myself.

It is available as an extension for Visual Studio 2015 and a stand-alone app, but the extension has been definitely more successful.

After an year and more than 7K downloads, I receive a lot of feedback and bug reports so I think it's an interesting tool for the developer community.

Recently, I have been interviewed on Code Snippet Studio by Syncfusion and the reason is that I used some controls from the Essentials Studio for WPF suite. They offer a free Community License which is perfect for an open source project like that.

Here you find the interview and please don't forget the project is open to contributions!


Alessandro

posted @ sabato 17 settembre 2016 12:13 | Feedback (0) | Filed Under [ Visual Studio 2015 ]

Introducing the Xamarin.Forms Starter Kit and the #XaMonday Show

I'm currently very busy with Xamarin.Forms for both development and training, so I decided to share some experiences I made with this platform.

First, I published an open source project on GitHub called the Xamarin.Forms Starter Kit. It's a basic news reader, but it includes a number of things such as SQLite local data access, connectivity check, data-binding, pull-to-refresh, and more.

It's here, and your contributions are welcome.

Secondly, I started a new video series on Channel9 called the #XaMonday Show, where I'll be publishing a new video about Xamarin.Forms every monday (hopefully!).

This is my way to share what I learn and to say thanks to all of those people who share what they learn and face with this platform every day.

Alessandro

posted @ sabato 17 settembre 2016 12:06 | Feedback (0) | Filed Under [ Xamarin ]

venerdì 2 settembre 2016

Xamarin.Forms: Enrich the UI with calendars and busy indicators with Syncfusion Essential Studio

As you might know, Syncfusion offers the very popular Essential Studio suite of controls for a huge number of development platforms, including Windows desktop, mobile, and Web.

One thing you might not know, is that Syncfusion is offering individuals and small businesses free access to the Essential Studio for free via the Community License. You can read more about this offer in this page.

Among the others, this offer includes Essential Studio for Xamarin. So, in this blog post I'm going to show how to use a couple controls in a Xamarin.Form app for Android, iOS, and Windows. More specifically, I'll show how to create a cross-platform news reader for the popular Channel9 web site enriching the UI with the BusyIndicator and Calendar controls. I assume you are a bit familiar with creating a Xamarin.Forms app and with LINQ, so I won't cover this in details and I will focus more thoroughly on implementing Syncfusion controls, as well as discussing some goodies in Xamarin.Forms that you might not be familiar with, such as pull-to-refresh.

Having that said, create a new blank Xamarin.Forms app called Channel9Browser using the Portable Class Library template.

The goal
The final result we want to reach is shown in the following figures, both based on the UWP app version:





The Calendar control will be used to filter the list of videos based on the selected date.

The source code for the sample app can be downloaded from https://github.com/alessandrodelsole/sfchannel9browser.

Quick intro
As an introduction, I will first describe the most important characteristics of the BusyIndicator and Calendar controls. The reason is that I want you to already know about these information before I discuss the ViewModel later.
The BusyIndicator control differs from the Xamarin's ActivityIndicator in that it exposes an AnimationType property, which allows to select among a number of different animations for different scenarios, and it also allows customizing the indicator's size via two properties, ViewBoxWidth and ViewBoxHeight. It is so simple to use and very attractive at the same time. The Calendar control is also extremely easy to use and configure. Each calendar event is represented by an instance of the CalendarInlineEvent class, which provides properties that map any possible event information, such as start/end time, subject, location, and even a different color for each event. Also, Calendar exposes a property called CalendarEventCollection, which you populate with a list of CalendarInlineEvent objects. Because this collection inherits from ObservableCollection<CalendarInlineEvent>, it can be easily data-bound to the Calendar control in order to show a list of events with no effort.

Adding references
Before we do anything else, we must add references to the libraries that offer the controls. These are located under C:\Program Files (x86)\Syncfusion\Essential Studio\version_number\Xamarin\lib, where version_number is the Essential Studio version you have installed on your machine. Notice how there are subfolders containing platform-specific version of the required libraries. For the PCL project, select and add the Syncfusion.SfBusyIndicator.XForms.dll and Syncfusion.SfCalendar.XForms.dll libraries from the pcl subfolder. For each platform-specific project you want to target, add the related references you find in the proper subfolders. For instance, for the Android project you can find the Syncfusion.SfBusyIndicator.Android.dll, Syncfusion.SfBusyIndicator.XForms.Android.dll, and Syncfusion.SfBusyIndicator.XForms.dll libraries under the android subfolder. Select the same libraries for the other platform-specific projects, changing the platform of course, and repeat the steps for the SfCalendar control.

Defining the model
The sample app has the goal of downloading news from the Channel9 web site in the form of RSS feeds. Every item in the news feed must be represented with a class that we call Item and that is defined as follows:

public class Item : INotifyPropertyChanged 
{
     private string title;
     public string Title
     {
         get
         {
             return title;
         }
         set
         {
             title = value;
             OnPropertyChanged(nameof(Title));
         }
     }
     private string link;
     public string Link
     {
         get
         {
             return link;
         }
         set
         {
             link = value;
             OnPropertyChanged(nameof(Link));
         }
     }
     private string author;
     public string Author
     {
         get
         {
             return author;
         }
         set
         {
             author = value;
             OnPropertyChanged(nameof(Author));
         }
     }
     private DateTime pubDate;
     public DateTime PubDate
     {
         get
         {
             return pubDate;
         }
         set
         {
             pubDate = value;
             OnPropertyChanged(nameof(PubDate));
         }
     }
     private string thumbnail;
     public string Thumbnail
     {
         get { return thumbnail; }
         set
         {
             thumbnail = value;
             OnPropertyChanged(nameof(Thumbnail));
         }
     }
     public event PropertyChangedEventHandler PropertyChanged;
     private void OnPropertyChanged(string propertyName)
     {
         this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }
}


The INotifyPropertyChanged interface implementation is required to raise notifications every time a property value changes. Do not forget to add a using System.ComponentModel directive. Notice the Thumbnail property, that will store the link of a thumbnail that Channel9 provides for each video. The next step is defining a class that downloads the news from the Internet and returns a collection of Item objects. This class is called ItemService, defined as follows (I'll make the necessary considerations later):

public static class ItemService 
{
     public static string FeedUri = "https://channel9.msdn.com/Blogs/MVP-VisualStudio-Dev/RSS";
     private static XNamespace mediaNS = XNamespace.Get("http://search.yahoo.com/mrss/");
     private static string GetThumbnail(XElement node)
     {
         var images = node.Descendants(mediaNS + "thumbnail");
         string imageUrl;
         switch(Device.Idiom)
         {
             case TargetIdiom.Phone:
                 imageUrl = images.FirstOrDefault().Attribute("url").Value;
                 break;
             default:
                 if (images.Count() > 1)
                 {
                     imageUrl = images.Skip(1).FirstOrDefault().Attribute("url").Value;
                 }
                 else
                 {
                     imageUrl = images.FirstOrDefault().Attribute("url").Value;
                 }
                 break;
          }
         return imageUrl;
     }

     // Query the RSS feed with LINQ and return an IEnumerable of Item
     public static async Task<IEnumerable<Item>> QueryRssAsync(CancellationToken token)
     {
         try
         {
             var client = new HttpClient();
             var data = await client.GetAsync(new Uri(FeedUri), token);
             var actualData = await data.Content.ReadAsStringAsync();
             var doc = XDocument.Parse(actualData);
             var dcNS = XNamespace.Get("http://purl.org/dc/elements/1.1/");
             var query = (from video in doc.Descendants("item")
                          select new Item
                          {
                              Title = video.Element("title").Value,
                              Author = video.Element(dcNS + "creator").Value,
                              Link = video.Element("link").Value,
                              Thumbnail = GetThumbnail(video),
                              PubDate = DateTime.Parse(video.Element("pubDate").Value,
                                  System.Globalization.CultureInfo.InvariantCulture)
                          });
             return query;
         }
         catch (OperationCanceledException)
         {
             return null;
         }
         catch (Exception ex)
         {
             return null;
         }
     }
 }

Following is a list of useful considerations:

  • the FeedUrl field contains the URL for the news feed;
  • Channel9's news feed contains a list of thumbnails, in different resolutions, for each video. For this reason, a special method called GetThumbnail retrieves the appropriate thumbnail resolution according to the device type the app is running on. The device type can be retrieved using the Idiom property from the Xamarin.Forms.Device class.
  • The QueryRssAsync method returns a collection of Item objects that will be used shortly.

The ViewModel

Typically, a ViewModel is a class that connects the model to the user interface. I'm not implementing the MVVM pattern here because I can't assume all of you know about it, but I'll be declaring a class that exposes objects to the user interface the proper way. This is also the place where we get started with some objects from Syncfusion. Our ViewModel must expose a collection of Item objects to the user interface, but it will also expose a collection of calendar events, each representing the publication date of a video on Channel9 and that will be data-bound to the Calendar control for filtering videos based on the selected date. The Syncfusion.SfCalendar.XForms namespace exposes the CalendarEventCollection class, which inherits from ObservableCollection<CalendarInlineEvent>. Following is the code for the ViewModel class, and I'll make some considerations later:

public class ItemViewModel : INotifyPropertyChanged 
{
     private bool isBusy;
     public bool IsBusy
     {
         get
         {
             return isBusy;
         }
         set
         {
             isBusy = value;
             OnPropertyChanged();
         }
     }
     public ObservableCollection<Item> Items { getset; }
     public ObservableCollection<Item> FilteredItems { getset; }
     public CalendarEventCollection VideoDates { getset; }
     public ItemViewModel()
     {
         this.Items = new ObservableCollection<Item>();
         this.VideoDates = new CalendarEventCollection();
     }
     public void FilterByDate(DateTime date)
     {
         this.FilteredItems = new ObservableCollection<Item>(this.Items.Where(i => i.PubDate.Date == date.Date));
     }
     public event PropertyChangedEventHandler PropertyChanged;
     public void OnPropertyChanged([CallerMemberName]string name = "") => PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(name));
     public async Task InitializeAsync()
     {
         if (IsBusy)
             return;
         IsBusy = true;
         try
         {
             var result = await ItemService.QueryRssAsync(new System.Threading.CancellationToken());
             if (result != null)
             {
                 this.Items = null;
                 this.Items = new ObservableCollection<Item>(result);
                 this.VideoDates.Clear();
                 foreach (var item in this.Items)
                 {
                     var videoEvent = new CalendarInlineEvent();
                     videoEvent.StartTime = item.PubDate;
                     videoEvent.EndTime = item.PubDate;
                     videoEvent.Subject = item.Title;
                     videoEvent.Color = Color.Maroon;
                     this.VideoDates.Add(videoEvent);
                 }
             }
         }
         catch (Exception)
         {
             return;
         }
         finally
         {
             IsBusy = false;
         }
     }
 }
Now a list of key concepts in this class:

  • it implements the INotifyPropertyChanged interface to notify callers of any changes in property values;
  • it exposes the IsBusy property that will be data-bound to the user interface to make it look busy while loading data;
  • it exposes the InitializeAsync method, which is responsible for downloading the list of news from the Internet and creating a proper collection;
  • it exposes a property called VideoDates, of type CalendarEventCollection, which stores the list of publication dates and that will be data-bound to the Calendar control
  • VideoDates is populated with instances of the CalendarInlineEvent class. This is done with a for..each loop over the collection of news returned from Channel9, where each contains the publication date;
  • for each calendar event, you can specify the start/end time, the subject, and the color. Of course, you can customize events further by specifying other information such as the location.


The App class
The App class is the place where we declare a variable of type ItemViewModel that will be shared to all pages. The code to add is simply the following:

internal static ItemViewModel viewModel;
public App()
{
     InitializeComponent();
     viewModel = new ItemViewModel();
     MainPage = new NavigationPage(new MainPage());
}

The User Interface

The sample app is made of four pages: the main page, a page for viewing the original content on Channel9, a page for selecting dates, and a page that shows a list of filtered videos. Let's start with the main page, whose code requires adding the XML namespaces for Syncfusion's controls at the top and that looks like the following:

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:local="clr-namespace:Channel9Browser"
              xmlns:busyindicator="clr-namespace:Syncfusion.SfBusyIndicator.XForms;assembly=Syncfusion.SfBusyIndicator.XForms"
              x:Class="Channel9Browser.MainPage">
   <StackLayout>
     <busyindicator:SfBusyIndicator x:Name="busyindicator" AnimationType="HorizontalPulsingBox" IsBusy="False" IsVisible="False" />
     <Button x:Name="FilterButton" Text="Filter by date" Clicked="FilterButton_Clicked" />
     <ListView x:Name="RssView" ItemsSource="{Binding Items}" IsPullToRefreshEnabled="True"
               Refreshing="RssView_Refreshing"
               IsRefreshing="{Binding IsBusy, Mode=OneWay}"
                ItemTapped="RssView_ItemTapped" >
       <ListView.SeparatorColor>
         <OnPlatform x:TypeArguments="Color" iOS="Transparent"/>
       </ListView.SeparatorColor>
       <ListView.ItemTemplate>
         <DataTemplate>
           <ViewCell>
             <StackLayout Padding="2">
               <Image Source="{Binding Thumbnail}" Aspect="AspectFit" />
               <Label Text="{Binding Title}" TextColor="#f35e20" />
               <Label Text="{Binding Author}" />
               <Label Text="{Binding PubDate}" TextColor="#503026" />
             </StackLayout>
           </ViewCell>
         </DataTemplate>
       </ListView.ItemTemplate>
     </ListView>
   </StackLayout>
 </ContentPage>
Key points:

  • the BusyIndicator control provides the IsBusy property, which enables the control animation when True;
  • its AnimationType property allows you to select among a number of built-in animations, such as HorizontalPulsingBox, Globe, Battery, Print. Check out the documentation for a comprehensive list of supported animations and figures. In this case I'm using the HorizontalPulsingBox, but there are some animations that are specific to some scenarios (e.g. Print).
  • you can assign the ViewBoxWidth and ViewBoxHeight properties with a fixed value in order to make it larger or smaller according to your needs.
  • the ListView control offers the pull-to-refresh capability with the IsPullToRefreshEnabled property. When True, you can handle the Refreshing event and make the UI look busy with the IsRefreshing property (in this case it's bound to the same-named property in the ViewModel).

Also, notice how the controls inside the ListView's data template are data-bound to properties of the Item class. In the C# code-behind, we have to load contents and respond to events. This is the code (key points at the end):

public partial class MainPage : ContentPage 
{
     public MainPage()
     {
         InitializeComponent();
         this.BindingContext = App.viewModel;
         switch(Device.Idiom)
         {
             case TargetIdiom.Desktop:
                 this.RssView.RowHeight = 288;
                 break;
             default:
                 this.RssView.RowHeight = 123;
                 break;
         }
     }
     private async Task LoadDataAsync()
     {
         this.busyindicator.IsVisible = true;
         this.busyindicator.IsBusy = true;
         await App.viewModel.InitializeAsync();
         this.RssView.ItemsSource = App.viewModel.Items;
         this.busyindicator.IsVisible = false;
         this.busyindicator.IsBusy = false;
     }

     private async void RssView_Refreshing(object sender, EventArgs e)
     {
         await LoadDataAsync();
     }
     protected async override void OnAppearing()
     {
         base.OnAppearing();
         await LoadDataAsync();
     }
     private async void RssView_ItemTapped(object sender, ItemTappedEventArgs e)
     {
         var selected = e.Item as Item;
         if (selected != null)
             await App.Current.MainPage.Navigation.PushAsync(new WebContentPage(selected.Link));
     }
     private void FilterButton_Clicked(object sender, EventArgs e)
     {
         App.Current.MainPage.Navigation.PushAsync(new CalendarPage());
     }


Notice how the Device.Idiom property allows to detect the device type the app is running on; if this is a desktop machine (typically Windows), we resize the ListView rows to make them a bit larger. The key point here is the LoadDataAsync method, not only because it downloads data from the Internet but because it enables and disables the BusyIndicator control by simply setting the IsVisible and IsBusy properties. The Refreshing event handler is invoked when the pull-to-refresh gesture is intercepted, while the ListView.ItemTapped and Button.Clicked event handlers are respectively invoked when the user taps an item in the collection of news and when the user wants to filter news by date. The second page is called WebContentPage.xaml and displays the original Web page on Channel 9. Both the UI and the code-behind are very simple and use the WebView control:

<?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="Channel9Browser.Pages.WebContentPage">
   <WebView x:Name="WebView1"/>
 </ContentPage>

public partial class WebContentPage : ContentPage
{
     string link;
     public WebContentPage(string link)
     {
         InitializeComponent();
         this.link = link;
     }
     protected override void OnAppearing()
     {
         base.OnAppearing();
         WebView1.Source = link;
     }
 }
The third page is called CalendarPage.xaml and uses the Calendar control. Let's see the code first, then let's make some considerations:

<?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:calendar="clr-namespace:Syncfusion.SfCalendar.XForms;assembly=Syncfusion.SfCalendar.XForms"
              x:Class="Channel9Browser.Pages.CalendarPage">
   <StackLayout>
     <Label Text="Select a date"/>
     <calendar:SfCalendar x:Name="calendar" VerticalOptions="FillAndExpand"
                HorizontalOptions="FillAndExpand"
                 SelectionMode="SingleSelection"
                 ViewMode="MonthView"
                 ShowInlineEvents="true"
                 DataSource="{Binding}"/>
     <Button x:Name="GoButton" Text="Go!" Clicked="GoButton_Clicked"/>
   </StackLayout>
 </ContentPage>
There is a new XML namespace called calendar, that points to the proper namespace in the Syncfusion's library. The Calendar control has a number of interesting properties, such as SelectionMode, ViewMode, and ShowInLineEvents. The latter is very important because, when True, it allows to display each CalendarInlineEvent when a date is selected. ViewMode is self-explanatory and supports MonthView and YearView values. SelectionMode allows to specify whether a user can select multiple dates, in this case we just allow SingleSelection for the sake of simplicity. The Calendar control is populated at runtime and via data-binding by assigning the DataSource property with an instance of the CalendarEventCollection class, in our case exposed by the ViewModel. The interesting thing is that you can interact with dates in a variety of ways; one is retrieving the selected date when the calendar is tapped, which is useful if we want to pass the date to another page. This is accomplished by handling the OnCalendarTapped event, which we do in the code-behind file as well as binding the CalendarEventCollection to the UI:

public partial class CalendarPage : ContentPage 
{
     private DateTime selectedDate;
     public CalendarPage()
     {
         InitializeComponent();
         this.calendar.OnCalendarTapped += Calendar_OnCalendarTapped;
         this.BindingContext = App.viewModel;
         this.calendar.BindingContext = App.viewModel.VideoDates;
     }
     private void Calendar_OnCalendarTapped(object sender, CalendarTappedEventArgs args)
     {
         SfCalendar calendar = args.Calendar;
         selectedDate = args.datetime;
     }
     private async void GoButton_Clicked(object sender, EventArgs e)
     {
         await App.Current.MainPage.Navigation.PushAsync(new FilteredVideosPage(selectedDate));
     }
 }

The CalendarTappedEventArgs class provides, among the other, a property called Calendar that represents the instance of the Calendar control; the latter exposes another property called datetime and that represents the selected date. This is passed to the last page, called FilteredVideosPage.xaml. This is similar to the main page, but provides a simplified UI in that it does not need to refresh and download the news feed, and it looks like this:

<?xml version="1.0" encoding="utf-8" ?> 
<
ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Channel9Browser.Pages.FilteredVideosPage">
   <StackLayout>
     <ListView x:Name="RssView" ItemsSource="{Binding FilteredItems}" IsPullToRefreshEnabled="True"
               ItemTapped="RssView_ItemTapped">
       <ListView.SeparatorColor>
         <OnPlatform x:TypeArguments="Color" iOS="Transparent"/>
       </ListView.SeparatorColor>
       <ListView.ItemTemplate>
         <DataTemplate>
           <ViewCell>
             <StackLayout Padding="2">
               <Image Source="{Binding Thumbnail}" />
               <Label Text="{Binding Title}" TextColor="#f35e20"/>
               <Label Text="{Binding Author}"/>
               <Label Text="{Binding PubDate}" TextColor="#503026"/>
             </StackLayout>
           </ViewCell>
         </DataTemplate>
       </ListView.ItemTemplate>
     </ListView>
   </StackLayout>
 </ContentPage>

This time the binding is against the FilteredItems collection from the ViewModel. At the code-behind level, the code is very similar to the main page but it does not support pull-to-refresh and it must invoke the FilterByDate method in the ViewModel. This is required for two reasons: it performs a LINQ query to filter the news by date and it ensures filtering is performed by comparing only the date part of a DateTime object. This is the code:

public partial class FilteredVideosPage : ContentPage 
{
     private DateTime filterDate;
     public FilteredVideosPage(DateTime filterDate)
     {
         InitializeComponent();
         switch (Device.Idiom)
         {
             case TargetIdiom.Desktop:
                 this.RssView.RowHeight = 288;
                 break;
             default:
                 this.RssView.RowHeight = 123;
                 break;
         }
         this.filterDate = filterDate;
         App.viewModel.FilterByDate(filterDate);
         this.BindingContext = App.viewModel;
     }
     private async void RssView_ItemTapped(object sender, ItemTappedEventArgs e)
     {
         var selected = e.Item as Item;
       if (selected != null)
             await App.Current.MainPage.Navigation.PushAsync(new WebContentPage(selected.Link));
     }
     protected override void OnAppearing()
     {
         base.OnAppearing();
         this.RssView.ItemsSource = App.viewModel.FilteredItems;
     }
}

Testing the App
You can now select your favorite platform and test the sample app using these nice controls from Syncfusion. Do not forget to check the developer documentation and the full list of available products in the Syncfusion web site.

Alessandro

posted @ venerdì 2 settembre 2016 05:54 | Feedback (0) | Filed Under [ Xamarin ]

mercoledì 24 agosto 2016

Get Syncfusion's mobile controls with Visual Studio Dev Essentials

A few months ago, Microsoft announced Dev Essentials, a program that allows developers to get a number of tools to build high-quality applications at no cost. In fact, Dev Essentials includes Visual Studio 2015 Community, Visual Studio Team Services, and Visual Studio Code.

Among the others, if you subscribe for Dev Essentials you will also get Syncfusion's Essential Studio for Xamarin and for UWP for free! This is an incredible opportunity: as a Microsoft and Xamarin partner, Syncfusion produces amazing and easy-to-use controls that will let you be more productive than ever and will give you an option to create beautiful, responsive, and attractive apps for both business and entertainment.

Check it out!

Alessandro

posted @ mercoledì 24 agosto 2016 13:20 | Feedback (0) | Filed Under [ Visual Studio 2015 ]

Powered by:
Powered By Subtext Powered By ASP.NET