Light up Your Modern Apps with DevExtreme

Editor' Note: This product was updated and renamed from DXTREME to DevExtreme.

With the release of Windows 8, and the remarkable PCs and devices such as the Microsoft Surface that it powers, you’ve probably seen some rich, interactive, modern applications, and wondered how you can build them for yourself. Developer Express has always been a leader in creating controls and add-ons to the development environment that make the task of building applications as easy as possible, and Windows 8 application development is no exception.

DXTREME (http://www.devexpress.com/subscriptions/DXTREME) is a new set of development tools that will allow you to build apps for this platform using XAML, as well as building for multiple mobile platforms using JavaScript and HTML. In this article, you’ll go end-to-end in building a rich, interactive application for Windows 8 using DXTREME XAML Controls.

The Application – Twitter Sentiment Search

The application that you’ll build in this article is one that allows you to search for a term on Twitter, display the most recent tweets about that term in a visual way, including pins on a map, and calculate a sentiment about those terms, so you can see if people are saying good things, bad things or neutral things about whatever you are interested in.

You can see a screenshot of the app in Figure 1. It is a panoramic app, touch-friendly allowing you to swipe across it to see new data.


Figure 1. The Tweet Search App

As you pan across the screen, you’ll see different information, including a chart of the most frequent tweeters, a map, and a character whose expression will change based on the sentiment. Sometimes he’s happy because you’ve said nice things. Sometimes he’s not. See Figure 2.


Figure 2. More information on the Tweet Search App

Building an application like this, with this much rich functionality might sound to be a very difficult proposition. But, thankfully, when using DXTREME, a lot of the hard work of the user interface is done for you. As you step through this article, you’ll see just how straightforward it can be. This will allow you, as a developer, to focus your time on what makes your application unique – in this case searching Twitter and aggregating the information, etc., so that you can provide greater value for your end users.

Introducing DXTREME

The DXTREME XAML Controls suite provides a number of different controls that your application can take advantage of. These controls come in a number of different groups:

  • Application Layout Controls are perhaps the single most useful set of controls, and something you’ll find indispensable as you build modern, Windows 8 applications. They provide the different types of views that you can have in your app, such as pages, tabbed views, sliding views, etc. The Twitter application uses Application Layout Controls extensively, making for example, the panoramic ‘sliding’ very straightforward.
  • Charts – DXTREME offers two types of charts, the Cartesian chart, which allows you to do standard bar, line, time series charts, etc. The Bar chart showing the tweeters in Figure 2 is an example of this. The Pie chart, which gives you a simple-to-implement pie chart, is seen in Figure 1.
  • Gauges are visualizations that offer a real-time view of rapidly changing data. Examples of these are Circular gauges that show information represented by a needle pointing to the arc of a circle, like a speedometer in a car or Linear gauges that show an example of an amount as a percentage of a filled line, like you would see with a thermometer.
  • Grids are, as the name suggests, controls that allow you to display data on a spreadsheet-like interface. They can be data bound, making the creation of dashboard style apps very straightforward.
  • Maps are, as their name suggests, controls that allow you to easily add an interactive map to your application. The DXTREME map control supports multiple mapping back-ends including Bing Maps, and the rights-free Open Street Map (http://www.openstreetmap.org).

You can download DXTREME from http://www.devexpress.com/Subscriptions/DXTREME/.

When you install DXTREME, you get all of the controls in these categories, as well as a number of Visual Studio 2012 templates that give you a quick start. Once installed, you’ll see the Windows 8 XAML control panel on your start screen. Launch it and you’ll see the desktop app from Figure 3.


Figure 3. Windows 8 XAML Controls Panel.

The Feature Demo contains a number of small, sample applications, focused on scenarios for a particular control. As a developer, you’ll find these extremely useful. It’s all too easy to get a new set of controls, only to find them buried in a big sample app and hard to learn from! But with DXTREME, the Feature Demo is your friend, giving you the code and the XAML that you need to implement a particular control.

You can see an example of this in Figure 4, where the Pie Chart control is shown.


Figure 4. Pie Chart in Feature Demo app.

Clicking on ‘Code’ on the top right hand side of the screen will show the XAML and/or C# code that is needed to implement a particular feature. It’s an extremely useful learning tool.

And, of course, in addition to the feature demos, the control panel also has a ‘Solution Demo,’ which is a full featured, real-world-like app (it uses dummy data), that shows off the type of application that is possible in Windows 8 with DXTREME.

It’s a Financial Tracker application, allowing you to look at a number of accounts, and their balances, etc. You can see it in Figure 5.


Figure 5. The Financial Application

In addition to all this, Visual Studio also has a bunch of new project templates and item templates that will allow your development to get up and running more quickly. You can see these as Windows Store items in Visual Studio 2012. See Figure 6.


Figure 6. DXTREME Templates in Visual Studio

All of these tools are useful to help you learn how to build a better app using DXTREME. For the rest of this article you’re going to roll your sleeves up and build your own, seeing how it’s done, step by step.

Getting Started with the Twitter App

To get started with the Twitter App, launch Visual Studio 2012 and choose the DXTREME 12.2 Blank App (XAML) template from the Windows Store Section in the templates list, as shown in Figure 6.

Call it ‘TweetSentiment’, and Visual Studio will create the project for you. This project will contain a page called MainPage.xaml containing a PageAdornerControl from DXTREME.

This control provides the ‘header’ for a Windows 8 page, where the title of the current page is rendered at the top, and ‘back’ navigation to the previous page, if you are clicking through, is available.

The text at the top of the page is data bound to the page’s view model, so to change it from the default ‘Header’ to a value such as ‘Twitter Search’, simply go to the view model for the page MainPageViewModel.cs and edit the property. You can do this at design or run time, but it’s a good idea to set the default value at design time. Simply edit the code in the view model constructor to read ‘Twitter Search’.

Run your app and you’ll see something like Figure 7.


Figure 7. Running the app.

It may not look like much right now, but it’s the beginnings of your app. In the next section, you’ll see how to create the view models that give you the results of a tweet search.

Light up Your Modern Apps with DXTREME - Page 2

Building the Models and View Models

Twitter search provides two useful APIs. One that allows you to search for tweets matching a criteria, and another for tweets matching distance from a location. We’ll use the former in determining sentiment, and the latter in rendering maps. One reason for this is that when we search tweets, we’re getting the ‘n’ most recent tweets. These don’t necessarily have location information in them, and from experimentation, this data is quite infrequent. So, in parallel to that, a separate search for ‘n’ recent tweets containing a location is also performed.

In order to do this, the most efficient way is to build View Models, which you will then bind your user interface to. As such, you’re going to build 2 View Models – one for tweets, and one for tweet locations.

I won’t go through all the code in this text, but it’s available for you in the download accompanying this article.

Before building the View Models, we’ll create some basic models that they will use. These models represent a tweet (called Tweet), the person who tweeted (called Tweeter) and the location of a tweet (called TweetLocation).

Creating the Models

Create a folder in your solution, and call it ‘Model’. In this, create three classes, called Tweet.cs, Tweeter.cs and TweetLocation.cs.

These will contain properties that contain the data that the search will populate, and that the user interface will bind to.

Figure 8 shows what your solutions will look like.


Figure 8. Your solution after adding the models.

Here’s the code for the Tweet class. Note that the namespace is the name of the project (TweetSentiment) followed by a dot followed by the name of the folder in which you put the class (Model). So if you do something different, make sure that the namespace matches what you have in your project.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TweetSentiment.Model
{
    class Tweet
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public string ImageUri { get; set; }
        public string currentText { get; set; }
        public string translatedText { get; set; }
        public string AuthorID { get; set; }
        public string pubDate { get; set; }
    
    }
}

Here’s the code for the Tweeter class. This is primarily used for the tweeters cartesian chart, where the count of tweets by tweeters is rendered.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TweetSentiment.Model
{
    class Tweeter
    {
        public string Author { get; set; }
        public int TweetCount { get; set; }
  
    }
}

Finally, here’s the TweetLocation class, which is used by the map to plot tweet locations.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TweetSentiment.Model
{
    class TweetLocation
    {
        public string
 Address { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
  
    }
}

Now that you have the models, let’s look at the first view model that you’ll build – the Tweets view model. This class will represent your set of tweets. It will periodically find the 20 most recent tweets matching your criteria, and expose that to the user interface. It will also keep a running record of these tweets, so that upon the next search those 20 will not be lost. This historic record will provide sentiment details.

Building the Tweets View Model

Add a new folder to your solution called ViewModels, and add a class to this called TweetsViewModel.cs. When you’re done, your solution should look like Figure 9.


Figure 9. Adding the View Model

In this class, you’ll have three private List<T> classes:

        private List<Tweet> _tweets = new List<Tweet>();
        private List<Tweet> _alltweets = new List<Tweet>();
        private List<Tweeter> _tweeters = new List<Tweeter>();

The first is for the most recent set of tweets found by search, the second for the aggregate list of all tweets found during the time the app is running, the third is the overall list of tweeters.

The list of tweets, and the list of tweeters will be exposed via properties because the UI needs to bind to them. The list of all tweets is kept internal. The sentiment count (which tweets are good, bad or neutral) will be run against this list, and the results exposed via properties. You’ll see this in the next section.

Here are the properties for exposing the list of tweets and the list of tweeters.

        public List<Tweeter> tweeters
        {
            get { return _tweeters; }
            set { _tweeters = value; }
        }
        public List<Tweet> tweets
        {
            get { return _tweets; }
            set { _tweets = value; }
        }

When using a View Model and binding a DXTREME control to it, you can have the binding update upon a property change event being raised. You need to implement this on your View Model, but it’s very straightforward.

To do this, remember that your class needs to expose the INotifyPropertyChanged interface:

public class TweetsViewModel : INotifyPropertyChanged

Then implement a simple PropertyChangedEventHandler function, like this:

public event PropertyChangedEventHandler PropertyChanged;

private void RaisePropertyChanged(string propertyName)
{
  PropertyChangedEventHandler handler = PropertyChanged;
  if (handler != null)
  {
  handler(this, new PropertyChangedEventArgs(propertyName));
  }
}

Now, when you use the code ‘PropertyChanged(“string”)’, anything that subscribes to the event will receive a notification.

Getting the tweets is very straightforward using an HTTP request. The following code will use an HTTP client to search Twitter for your search term, and load the results into an XDocument. This can then be queried using Linq to create the List<Tweet> of tweets. The new list is then inserted into the master list, and translation and sentiment counts are done.

Here’s the code:

private async void getTweets(string _searchTerm)
{
  try
  {
    var httpClient = new HttpClient();
    var result = httpClient.GetStringAsync("http://search.twitter.com/search.rss?rpp=20&q=" + _searchTerm);
 
    var document = XDocument.Parse(result.Result);
    var ns = (XNamespace)"http://base.google.com/ns/1.0";
    string strLink = 
        document.Descendants("item").First().Descendants("link").First().ToString();
    string id = getTwitterID(strLink);
    if (id != _last_id)
    {
      List<Tweet> tweets = (from item in document.Descendants("item")
        select new Tweet()
        {
          Title = (string)item.Descendants("title").First(),
          currentText = (string)item.Descendants("title").First(),
          Author = (string)item.Descendants("author").First(),
          pubDate = (string)item.Descendants("pubDate").First(),
          ImageUri = (string)item.Descendants(ns + "image_link").First()
        }).ToList();
 
        _alltweets.InsertRange(0, tweets);
        _tweets = _alltweets.Take(20).ToList();
 
        _last_id = id;
        DoSentimentCount(tweets);
        DoAuthorCount();
      }
    }
    catch(Exception e)
    {
    }
    RaisePropertyChanged("tweets");
  }
 

Translation is achieved using the Microsoft Translator API. For details on how to use this, visit http://www.microsofttranslator.com. It offers a free tier that gives you translation of 2 million characters per month. You’ll need to sign up for it in order to get a Client ID and Client Secret to use the service. The download code has placeholders for these and will not work without them.

The Sentiment count is a function that matches certain words as positives and certain words as negatives. If these words are encountered, then counters of these words for the entire set and the recent set of tweets are updated.

Light up Your Modern Apps with DXTREME - Page 3

Building the Locations View Model

The locations view model is very similar to the tweet search one in that it exposes List<T> of data, and provides methods that can be called to update that data by providing new searches.

One important point before going further is that this requires you to use a Bing Maps API key, which you can obtain for free by registering for a Bing Maps developer account at: http://www.microsoft.com/maps/

This API key is used in two ways. First, Twitter returns very basic information about a location, such as “Seattle, WA”, so the View Model will call the Bing Maps service to turn this into Latitude and Longitude, which we can plot on the DXTREME Map control in the view. Second, the DXTREME Map control needs to be initialized using one of these API keys in order to use Bing Maps. So it’s a good idea to go and get one now!

The Bing service that provides geo coding (turning location name into latitude / longitude) is found at: http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl

Be sure to add a service reference to this and call it ‘geoCodeService’.

The Locations View Model searches for tweets within a certain distance of your PC’s current location. Windows 8 allows you to get the location, but first you, as a developer have to tell your app that it will use location. You do this by opening the packaging.appmanifest file and selecting the ‘Capabilities’ tab. Once you’ve done this, select ‘Location’. Now, when the app runs for the first time, the user will be asked if they will allow their location to be used. When they say ‘yes’, Windows 8 will get their current latitude and longitude and use that for searching Twitter for locations.

Here’s the code to search Twitter for tweets matching a location, which then geocodes the returned locations, and loads the contents into a List<TweetLocation>

private async void getTweets(string _searchTerm)
{
  bool b = await getDevicePosition();
  if (b)
  {
    geoCodeService.GeocodeRequest geocodeRequest = new geoCodeService.GeocodeRequest();
    geocodeRequest.Credentials = new geoCodeService.Credentials();
    geocodeRequest.Credentials.ApplicationId = "<Your App ID>";
    var httpClient = new HttpClient();
    string posVal = thispos.Coordinate.Latitude.ToString() + "," + 
        thispos.Coordinate.Longitude.ToString() + ",500mi";
    string searchVal = "http://search.twitter.com/search.rss?rpp=20&geocode=" + 
        posVal + "&q=" + _searchTerm;
    var result = httpClient.GetStringAsync(searchVal);
    var document = XDocument.Parse(result.Result);
    var ns = (XNamespace)"http://base.google.com/ns/1.0";
    if(document.Descendants("item").Count()>0)
    {
      string strLink = 
        document.Descendants("item").First().Descendants("link").First().ToString();
      string id = getTwitterID(strLink);
      if (id != _last_id)
      {
        List<TweetLocation> tweetlocations = 
          (from item in document.Descendants("item").Descendants(ns + "location")
            select new TweetLocation()
              {
              Address = item.Value
              }).ToList();
            foreach (TweetLocation loc in tweetlocations)
            {
              if (loc.Address != "")
              {
                geoCodeService.GeocodeServiceClient client = new 
                    geoCodeService.GeocodeServiceClient(new 
                        geoCodeService.GeocodeServiceClient.EndpointConfiguration());
                geocodeRequest.Query = loc.Address;
                geoCodeService.GeocodeResponse response = await 
                  client.GeocodeAsync(geocodeRequest);
                if (response.Results.Count() > 0)
                {
                  geoCodeService.GeocodeResult thisresult = 
                        response.Results[0] as geoCodeService.GeocodeResult;
                  if (thisresult.Locations.Count() > 0)
                  {
                    loc.Latitude = thisresult.Locations[0].Latitude;
                    loc.Longitude = thisresult.Locations[0].Longitude;
                  }
                }
 
              }
            }
            _alltweets.InsertRange(0, tweetlocations);
            _tweets = _alltweets.Take(100).ToList();
            _last_id = id;
            RaisePropertyChanged("tweets");
          }
       }
    }

And that’s it. So now you have your Models, you have your View Models, and the last thing you’ll need to incorporate are your Views. This is where DXTREME really shines.

Before doing this, one little thing will make your app dev easier. These View Models will be shared across a number of different views, so in order to have the same View Model shared across these, a singleton pattern is used.

Here’s the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace DXTweets
{
    public static class Locator
    {
        private static readonly TweetsViewModel _instance = new TweetsViewModel();
        private static readonly TweetsMapModel _mapinstance = new TweetsMapModel();
        public static TweetsViewModel Instance
        {
            get{ return _instance; }
        }
        public static TweetsMapModel MapInstance
        {
            get { return _mapinstance; }
        }
    }
 
   
}

So now, instead of setting the data context of a view to the View Model, setting it instead to a property of the Locator object will ensure that the same View Model is shared between views. The Locator.Instance will contain the TweetsViewModel, and the Locator.MapInstance will contain the TweetsMapModel.

Light up Your Modern Apps with DXTREME - Page 4

Building the Views with DXTREME

A common design pattern in Windows 8 apps is the panoramic one, where the app contains data in a ‘wide’ view that the user scrolls over horizontally. The News App, Xbox Music App and People apps that ship with Windows 8 are great examples of this.

DXTREME gives you a control that makes building these panoramic apps incredibly easy. It’s called the DXSlideView control. You simply place this on a page, such as MainPage.xaml, and it provides the sliding container. You then populate it with DXSlideViewItem controls. These are UserControls that you can create (you’ll see these in this section), which the DXSlideView lays out side by side and provides a sliding view of, managing things such as the appropriate width and placement of the header for you.

So if you look back at Figures 1 and 2, you’ll see for this Twitter app that there are 5 views: the Sentiment View, the Tweets List View, the Map View, the Tweeters View and the Character View, implementing the container that gives you a managed panorama of these is as easy as this with DXTREME:

<Grid>
  <dx:SlideView>
    <dx:SlideViewItem Header="Sentiment">
      <localViews:TweetSentiment/>
    </dx:SlideViewItem>
    <dx:SlideViewItem Header="Tweets">
      <localViews:TweetTiles/>
    </dx:SlideViewItem>
    <dx:SlideViewItem Header="Map">
      <localViews:TweetMapView/>
    </dx:SlideViewItem>
    <dx:SlideViewItem Header="Tweeters">
      <localViews:Tweeters/>
    </dx:SlideViewItem>
    <dx:SlideViewItem Header="What Dani thinks">
      <localViews:Character/>
    </dx:SlideViewItem>
  </dx:SlideView>
</Grid>

And that’s as simple as it can be – basically you create a SlideView, and then add SlideViewItems to it. You tell the SlideViewItem what its child control will be, and the controls do the rest for you.

So, let’s now look at each view, and how they are built using DXTREME Controls.

The Sentiment View

The Tweet Sentiment view is shown in Figure 10. It’s a very straightforward view, telling you the number of new tweets in the last search (it presently does a search every minute), and how many of them are positive and how many of them are negative in nature.


Figure 10. The Tweet Sentiment View.

First, to create a view like this, create a folder in your project called Views and add a new UserControl to it. Make sure that you use the UserControl type, because that is what the SlideViewItem expects to load.

This view uses a DXTREME Pie Chart to render the data. The XAML for this Pie Chart, with a custom palette is below. Note also the data is a DataPointCollection that contains a series of Data Points.

<Charts:PieChart x:Name="pieChart" Margin="10,0" ToolTipEnabled="True" VerticalAlignment="Stretch">
  <Charts:PieChart.Legend>
    <Charts:Legend HorizontalPosition="Center" 
        VerticalPosition="Bottom" Orientation="Horizontal"/>
    </Charts:PieChart.Legend>
    <Charts:PieChart.Palette>
      <Charts:CustomPalette>
        <Charts:CustomPalette.Colors>
          <Color>#F7921E</Color>
          <Color>#00A65A</Color>
          <Color>#BF1E2E</Color>
        </Charts:CustomPalette.Colors>
      </Charts:CustomPalette>
    </Charts:PieChart.Palette>
  <Charts:PieChart.Series>
    <Charts:Series>
      <Charts:Series.View>
        <Charts:PieSeriesView LegendPointPattern="{}{A}: {V}"/>
      </Charts:Series.View>
      <Charts:Series.Data>
        <Charts:DataPointCollection>
          <Charts:DataPoint Argument="Neutral" Value="0" />
          <Charts:DataPoint Argument="Positive" Value="0" />
          <Charts:DataPoint Argument="Negative" Value="0" />
        </Charts:DataPointCollection>
      </Charts:Series.Data>
    </Charts:Series>
  </Charts:PieChart.Series>
</Charts:PieChart>
 

Setting the data on the Pie Chart then becomes very straightforward. As the chart has a DataPointCollection set up, the following code will change the values of these data points, effectively redrawing the chart.

There are two ways that you can do this. First, as the chart is fully MVVM compliant, you can bind it to a data source. Or, if your data isn’t in a nice collection, as is the case here, you can also use code-behind to add values to the chart manually. Data isn’t often organized into nice collections for you by the back-end service, so it’s good to know that the chart gives you this type of flexibility.

Whenever the data changes, the ViewModel raises an event, as demonstrated earlier, and this code can run in response to that event.

        void updatePie()
        {
            DataPointCollection coll = pieChart.Series[0].Data as DataPointCollection;
            coll.Clear();
            coll.Add(new DataPoint("Neutral", Locator.Instance.total_neutral_count));
            coll.Add(new DataPoint("Positive", Locator.Instance.total_positive_count));
            coll.Add(new DataPoint("Negative", Locator.Instance.total_negative_count));
        }
 

In this case, as shown earlier, the Locator is a singleton containing the instance of TweetsViewModel, which exposes properties for the total counts of neutral, positive and negative sentiment, so we simply set the data points on the Pie Chart with these values.

The Tweet List View

Figure 11 shows the Tweets, presented in a template form where the tweet, and the name and picture of the tweeter are rendered.


Figure 11. The Tweets View

At the heart of this functionality is a DXGridView from the DXTREME Suite. This provides a grid-like view of data, which is easily templated, and which provides parameterized navigation functionality should you want it.

Here’s an example.

<Layout:DXGridView x:Name="tilesGrid" ItemTemplate="{StaticResource TweetTemplate}" 
		SelectionMode="None" ItemNavigationTargetType="TweetDetailsView" 
		ItemNavigationTargetParameterBinding="{Binding Author}"
		IsItemClickEnabled="True" ItemsSource="{Binding tweets}">
</Layout:DXGridView>

First off, the ItemTemplate property is used to define how you want the data that the grid renders to look. The item template used, to give the layout shown in Figure 11, is here:

<DataTemplate x:Key="TweetTemplate">
  <Grid>
    <Rectangle Fill="#3A4974" HorizontalAlignment="Left" Height="115" Margin="165,11,0,0" 
		Stroke="White" VerticalAlignment="Top" Width="300"/>
    <Path Data="M255.5,110.25 L237.5,119 L255.25,126.75" Fill="#3A4974" 
		HorizontalAlignment="Left" Height="17.5" Margin="148,21.75,0,0" Stretch="Fill" Stroke="White" UseLayoutRounding="False" VerticalAlignment="Top" Width="19"/>
    <TextBlock Foreground="#F7921E" HorizontalAlignment="Left" Height="50" 
		Margin="176,22,0,0" TextWrapping="Wrap" x:Name="txtTweet" Text="{Binding Title}" VerticalAlignment="Top" Width="277" FontSize="12"/>
    <TextBlock Foreground="#F7921E" HorizontalAlignment="Left" Height="50" 
		Margin="176,72,0,0" TextWrapping="Wrap" x:Name="txtTrans" Text="{Binding translatedText}" VerticalAlignment="Top" Width="277" FontSize="12"/>
    <Image Source="{Binding ImageUri}" HorizontalAlignment="Left" Height="89" 
		Margin="10,11,0,0" VerticalAlignment="Top" Width="116"/>
    <TextBlock Foreground="#F7921E" HorizontalAlignment="Left" Height="17" 
		Margin="10,109,0,0" TextWrapping="Wrap" Text="{Binding Author}" VerticalAlignment="Top" Width="150" FontSize="10"/>
  </Grid>
</DataTemplate>

It’s important to note the binding properties that are being used here. Note that each of them is a field in the Tweet class. The TweetsViewModel exposed a List<Tweet>, so each Tweet has properties that are bound to in the template, while the DXGrid itself is bound to the List<>.

You can see that in the DXGridView control here:

<Layout:DXGridView x:Name="tilesGrid" ItemTemplate="{StaticResource TweetTemplate}" 
		SelectionMode="None" ItemNavigationTargetType="TweetDetailsView" 
		ItemNavigationTargetParameterBinding="{Binding Author}"
		IsItemClickEnabled="True" ItemsSource="{Binding tweets}">
</Layout:DXGridView>

Another useful part of the DXGridView is that it can be used to generate navigation to other views. So, for example, if you wanted selecting a single tweet to navigate you to a new view containing all of the tweets for that user, you can do so by setting the ItemNavigationTargetType to an instance of the view that you want to load, and ItemNavigationTargetParameterBinding to a value that you want to pass to that view; so in this case you can pass the value of the Author property of the currently selected tile. The DXGridView is smart enough to derive this from the data template.

When it comes to the amount of code you need to write – it couldn’t be simpler.

 
public TweetTiles()
{
this.InitializeComponent();
this.DataContext = Locator.Instance;
Locator.Instance.PropertyChanged += Instance_PropertyChanged;
}
 
void Instance_PropertyChanged(object sender, 
System.ComponentModel.PropertyChangedEventArgs e)
{
this.DataContext = null;
this.DataContext = Locator.Instance;
}

The only thing you really need to do is to rebind the data whenever it changes. I’ve found that the above trick works really well. In code, you set the DataContext for the view to be Locator.Instance (the singleton holding the View Model), and subscribe to its PropertyChanged event.

Then, in reaction to that event being fired, clear the context, and reset it, and the grid will update to the new set of tweets!

Light up Your Modern Apps with DXTREME - Page 5

The Tweet Map View

The Tweet Map view plots the tweets on a map of the world as shown in Figure 12.


Figure 12. Plotting the Tweets on a Tweet Map View

Due to the way the Twitter Search API works, these aren’t necessarily the same tweets that the Tweets List from the previous section shows. Where that list gives you the 20 most recent tweets, this plots the 20 most recent that had a location, so that we can have some pins to put in the map!

The Map itself is implemented using the DXTREME Map control, like this:

<Map:MapControl x:Name="map" EnableAnimation="False" Background="#010413" ZoomLevel="2">
  <Map:MapControl.Layers>
    <Map:ImageTilesLayer>
      <Map:ImageTilesLayer.DataProvider>
        <Map:BingMapDataProvider Kind="Hybrid" 
          BingKey="<PUT YOUR BING KEY HERE"/>
      </Map:ImageTilesLayer.DataProvider>
    </Map:ImageTilesLayer>
  <Map:VectorItemsLayer>
  </Map:VectorItemsLayer>
  </Map:MapControl.Layers>
</Map:MapControl>

The control is built in a way to be flexible, so that it can use different mapping engines as the back end. These are specified using the ImageTilesLayer and DataProvider properties. When using Bing, you need to provide the Bing Key that you set up earlier.  In addition to this, the pins that go into the map will go in using the VectorItemsLayer, so an empty one is defined here, and it will be filled in at runtime.

Writing code to put the pins in the map is very straightforward:

public TweetMapView()
{
  this.InitializeComponent();
  this.DataContext = Locator.MapInstance;
  Locator.MapInstance.PropertyChanged += MapInstance_PropertyChanged;
            
}
 
void MapInstance_PropertyChanged(object sender, 
System.ComponentModel.PropertyChangedEventArgs e)
{
  (map.Layers[1] as VectorItemsLayer).Items.Clear();
  foreach (TweetLocation loc in Locator.MapInstance.tweets)
  {
    GeoPoint point = new GeoPoint();
    point.Latitude = loc.Latitude;
    point.Longitude = loc.Longitude;
    MapPushpin pin = new MapPushpin();
    pin.Location = point;
    VectorItemsLayer layer = map.Layers[1] as VectorItemsLayer;
    layer.Items.Add(pin);
  }
}

The constructor uses the Locator singleton to get an instance of the TweetsMapView View Model, and wires up a handler for when any of its properties change.

When they change, it’s simply a matter of getting the List<TweetLocation> that the View Model exposes, and then iterating through it to get the latitude and longitude of each entry. These can then be used to set up a GeoPoint class, which is the location of a Map Pin.

Of course, as before, if your data service exposes the list of pins as a collection, you could use MVVM and bypass needing to write this code.

The Tweeters View

The Tweeters view shows a bar chart (using the DXTREME Cartesian Chart control) of the people who have tweeted on your topic, by frequency of tweet.

You can see it in Figure 13.


Figure 13. The Tweeters View

This is implemented using the Cartesian chart with a custom color palette, like this:

<Charts:CartesianChart Rotated="True" x:Name="TweetersBarChart">
  <Charts:CartesianChart.Legend>
    <Charts:Legend/>
  </Charts:CartesianChart.Legend>
  <Charts:CartesianChart.Palette>
    <Charts:CustomPalette>
      <Charts:CustomPalette.Colors>
        <Color>#F7921E</Color>
        <Color>#00A65A</Color>
        <Color>#BF1E2E</Color>
      </Charts:CustomPalette.Colors>
    </Charts:CustomPalette>
  </Charts:CartesianChart.Palette>
  <Charts:CartesianChart.Series>
    <Charts:Series DisplayName="Tweeters">
      <Charts:Series.View>
        <Charts:StackedBarSeriesView />
      </Charts:Series.View>
      <Charts:Series.Data>
        <Charts:DataPointCollection ArgumentScaleType="Qualitative" x:Name="dpc">
        </Charts:DataPointCollection>
      </Charts:Series.Data>
    </Charts:Series>
  </Charts:CartesianChart.Series>
</Charts:CartesianChart>

The important part of this declaration to note is the DataPointCollection  in which the data points for the bars on the chart will be added. It’s blank at the moment, having no children, but will be set up as the view loads.

You can see the full code for the chart here:

public Tweeters()
{
  this.InitializeComponent();
  this.DataContext = Locator.Instance;
  Locator.Instance.PropertyChanged += Instance_PropertyChanged;
  DrawChart();
}
 
void Instance_PropertyChanged(object sender, 
  System.ComponentModel.PropertyChangedEventArgs e)
{
    DrawChart();
}
void DrawChart()
{
  List<Tweeter> tweeters = Locator.Instance.tweeters;
  DataPointCollection coll = TweetersBarChart.Series[0].Data as DataPointCollection;
  coll.Clear();
  var sortedlist = from t in tweeters
        orderby t.TweetCount descending
        select t;
 
  var toptweeters = sortedlist.Take(10).ToList();
  foreach (Tweeter t in toptweeters)
  {
    DataPoint d = new DataPoint();
    d.Argument = t.Author;
    d.Value = t.TweetCount;
    coll.Add(d);
  }
}
 

As with the previous views, this one uses the singleton to get the View Model, and sets up a property changed event handler. As the chart isn’t data bound, in the constructor we call a function called DrawChart, which also gets called whenever the properties change. This function updates the chart to show the appropriate tweeters.

The DrawChart function takes the full list of tweeters, and grabs the top 10 of them, when they are ordered descending, thus giving us the 10 most frequent tweeters. This list is then used to create DataPoint values, where the argument is the author, and the value is the count of their tweets. When these are all added, the chart will draw itself, using this collection of DataPoint objects, and give us the bar chart.

The Character View

For a little fun, we’ve also added a ‘Character’ view that gives you a different visualization of the data. A number of pre-rendered characters are added to the project, and these are produced randomly based on the sentiment of the tweets. So, for example, if tweets are positive, you may see something like Figure 14.


Figure 14. The Character reacts to a positive tweet.

Or, if they are negative, he might be less accommodating, like in Figure 15.


Figure 15. The Character reacts to negative tweets

This is also implemented using a View, albeit a very simple one.

It contains an Image, like this:

<Image Grid.Column="1" Grid.Row="1" Source="ms-appx:///Assets/neutral1.png" x:Name="imgChar"></Image>

The code then uses the same pattern as the rest of the views, where it uses the singleton to get the ViewModel, and sets up an event handler to catch any changes in the properties of the ViewModel.

public Character()
{
  this.InitializeComponent();
  DrawCharacter();
  Locator.Instance.PropertyChanged += Instance_PropertyChanged;
}
 
void Instance_PropertyChanged(object sender, 
 System.ComponentModel.PropertyChangedEventArgs e)
{
  DrawCharacter();
}
 
void DrawCharacter()
{
  string strRoot = "neutral";
            
  if (Locator.Instance.recent_positive_count > Locator.Instance.recent_negative_count)
  {
    strRoot = "happy";
  }
  else if (Locator.Instance.recent_negative_count >= 
           Locator.Instance.recent_positive_count)
  {
    strRoot = "sad";
  }
  else
  {
    strRoot = "neutral";
  }
 
  System.Random randSeed = new System.Random(System.DateTime.Now.Millisecond);
  int val = randSeed.Next(1, 3);
  string path = "/Assets/" + strRoot + val + ".png";
  Uri uri = new Uri(this.BaseUri, path);
  BitmapImage pic = new BitmapImage(uri);
  imgChar.Source = pic;
}

Based on the values of recent tweet counts, it then picks a state (happy, sad, neutral) , and picks a random image from the set, assigning it to the <Image> that you saw in the View declaration.

The AppBar

The Mainpage also includes a standard Windows 8 AppBar at the bottom. This control, as seen in Applications such as Internet Explorer hides off the bottom of the screen and is either swiped up using a touch screen, or with a right mouse click near the bottom of the screen.

In this app, you use the app bar to change the search term for tweets, or invoke a translation of the tweets. You can see it in Figure 16.


Figure 16. The AppBar

As the Main view uses a DXPage control, implementing an AppBar becomes very simple – as it exposes a BottomAppBar property for this very reason. This is important, because it shows that the DXTREME controls aren’t in a silo – they are first class Windows 8 citizens, and the DXPage instead of replacing the standard Page control, inherits from it, so as Microsoft updates the underlying runtime with security or bug fixes, your controls using DXTREME will take advantage of that.

 Here’s the XAML.

<Page.BottomAppBar>
  <AppBar x:Name="bottomAppBar" Padding="10,0,10,0">
    <Grid>
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
        <Button x:Name="btnTranslate" Content="Translate Tweets" 
                Click="btnTranslate_Click_1" />
      </StackPanel>
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
        <TextBox x:Name="txtSearchTerm" Width="300" Height="24"></TextBox>
        <Button Style="{StaticResource RefreshAppBarButtonStyle}" 
			  Click="Button_Click_1"/>
      </StackPanel>
    </Grid>
  </AppBar>
</Page.BottomAppBar>

As you may note, you don’t need to handle any logic for hiding or showing the bar – the DXPage does that for you. You only need to write the logic to handle the controls on the bar, such as invoking the translation of the tweets, or changing the search term.

Conclusion

Microsoft has created a new set of user interface guidelines, to keep up to date with the new paradigm of touch-first interfaces that are intended for use with devices such as Microsoft Surface. The intent of this is to establish a high quality and consistent baseline for all Windows applications.

Building apps for the Windows store is a new frontier for developers, with a lot of new paradigms that need to be learned. Anything that can help get some of the ‘grunt work’ done, is always a boon, and the DXTREME toolkit from DevExpress gives you a terrific shortcut with its XAML controls.

In this article you saw how some of these controls make it very straightforward to write rich, modern, Windows 8 applications that require minimal coding effort in the View layer. You created a fully functional Model View View Model (MVVM) application in C#, using many of the controls in this suite to see a real-world implementation.

This highlights the flexibility of the DXTREME XAML controls and how they empower you to be able to build applications that target Windows 8 Pro and WinRT. They work in conjunction with the native controls, and can be deployed easily to make Windows Store and business apps.

In the final analysis, what makes the real difference between apps that are useful and apps that are forgotten is their functionality, ease of use and user experience. By helping you develop the user interface layer to be rich, high performing and standardized, the DXTREME XAML controls enable you to focus on adding real value to your app by saving you time on ease of use and user experience, and allowing you to invest it in the business functionality of your app.

# # #

This site does business with DevExpress.



Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The Red Hat® Standard Operating Environment SOE helps you define, deploy, and maintain Red Hat Enterprise Linux® and third-party applications as an SOE. The SOE is fully aligned with your requirements as an effective and managed process, and fully integrated with your IT environment and processes. Benefits of an SOE: SOE is a specification for a tested, standard selection of computer hardware, software, and their configuration for use on computers within an organization. The modular nature of the Red …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds