50
7 Session 5.2 Using LINQ to read structured data

3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Embed Size (px)

Citation preview

Page 1: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

7

Session 5.2

Using LINQ to read structured data

Page 2: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone

Topics Structured data and LINQ Databases and objects Database queries and LINQ Creating Silverlight layout templates Databinding to lists Using LINQ queries to produce object

collections

Page 3: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone3

Reading Twitter XML feeds We can use a

WebClient request to read structured data from a web host

The Twitter feed information can be supplied as an XML structured data file

Our program must pull out some content and display it

Page 4: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone4

Reading the Twitter feed

This code will fetch the XML that describes a Twitter feed

The URL contains the Twitter username

private void loadButton_Click(object sender, RoutedEventArgs e){ string url = "http://twitter.com/statuses/user_timeline/" + nameTextBox.Text + ".xml";

client.DownloadStringAsync(new Uri(url));}

Page 5: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone5

XML structured data We have already seen XML in the

markup language used by Silverlight to describe pages

The XML for a Twitter feed contains elements and properties which are formatted to describe Twitter post information

We could write some C# to decode the feed, but we are going to use LINQ instead

LINQ stands for Language INtegrated Query

Page 6: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone6

LINQ LINQ is a technology that is part of

the .NET system libraries It builds on C# language features to

provide easy data transfer between structured data storage and the object models used by modern languages

It is well worth knowing about

Page 7: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone7

A diversion into databases If you want to store large amounts of

structured data you will not write a system to do this

Instead you will use a database The database manages the data for

you, and your program will send commands to it to add, remove and search for data

Page 8: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone8

A simple Database

We can start by considering a simple sales database

This is the customer table Each row describes a single customer

Name Address Bank Details Customer ID

Rob 18 Pussycat MewsNut East Bank 123456

Jim 10 Motor Drive Big Fall Bank 654322

Ethel 4 Funny Address Strange bank 111111

Page 9: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone9

Two other tablesSales tableCustomer ID Product ID Order Date Status

123456 1001 21/10/2010 Shipped

111111 1002 10/10/2010 Shipped

654322 1003 01/09/2010 On order

Product ID Product Name Supplier Price

1001 Windows Phone 7 Microsoft 200

1002 Cheese grater

Cheese Industries 2

1003 Boat hook John’s Dockyard 20

Product Table

Page 10: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone10

Using the database We can combine the information in

the tables to obtain transaction details Rob has Customer ID 123456 Customer ID 123456 ordered product

ID1001 1001 is the product ID of a Windows

Phone Rob bought a Windows Phone We get the database to do this for us

by issuing queries to it

Page 11: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone11

Database queries

This SQL query will create a table that contains all the orders placed by Rob

This result can then be used as the basis of another query

Database queries are much easier to create than the equivalent program statements to work through the data

SELECT * FROM Orders WHERE CustomerID = "123456"

Page 12: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone12

A C# sales database

If we wrote a C# program to store the sales database our starting point would be class designs

The above class holds Customer information

public class Customer{ public string Name {get; set;} public string Address { get; set; } string BankDetails { get; set; } public int ID { get; set; }}

Page 13: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone13

Holding multiple Customers

Once we have a class that contains the required data we can create collections of that object

Above we have created a list of customers

We can then store customers in the list by adding them to it

List<Customer> Customers = new List<Customer>();

Page 14: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone14

Searching for customers

This is the C# code that implements the SQL query we saw earlier

public List<Order> FindCustomerOrders(int CustomerID){ List<Order> result = new List<Order>(); foreach ( Order order in Orders ) { if (order.CustomerID == CustomerID) { result.Add(order); } } return result;}

Page 15: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone15

Databases and objects If object-oriented programs and

databases are to work together we need something to convert from database tables to objects and back

We can do this by creating of “glue” code that creates objects and stores them back in tables

However, this task is made much easier by LINQ

Page 16: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone16

A LINQ query

This is the LINQ code that implements the SQL query we saw earlier

It does not look like legal program statements, but it compiles perfectly

It is worth a closer look

var orderQueryResult = from order in db.Orders where order.CustomerID == "123456" select order;

Page 17: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone17

Query result

The query returns a result which is given the type var var means “a type which works here” The type of a var variable depends on

the context of the declaration In this case orderQueryResult will

hold a collection of var objects that look like orders

var orderQueryResult = from order in db.Orders where order.CustomerID == "123456" select order;

Page 18: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone18

Iteration source

This sets up the iteration through the elements in a table

The db variable represents the database connection and we are using the Orders table from that database

var orderQueryResult = from order in db.Orders where order.CustomerID == "123456" select order;

Page 19: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone19

Restriction operation

This is the restriction operation that identifies the orders to be selected from the table

In this case we are looking for orders with the CustomerID of 123456

var orderQueryResult = from order in db.Orders where order.CustomerID == "123456" select order;

Page 20: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone20

Selection operation

This identifies the item to be selected and added to the result when the restriction operation succeeds

This means that we will get a collection of var results that look like order objects

We can then use these objects in our program

var orderQueryResult = from order in db.Orders where order.CustomerID == "123456" select order;

Page 21: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone21

Databases on Windows Phone LINQ is a great way to combine object oriented code and databases

Unfortunately the present version of Windows Phone does not have database support

But it does contain the LINQ libraries This would seem a strange design

choice Fortunately LINQ can also be used to

read structured data and create objects from it

Page 22: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone22

Twitter XML

This is an abridged Twitter status XML file

<?xml version="1.0" encoding="UTF-8"?><statuses type="array"><status> <created_at>Tue Oct 12 11:57:37 +0000 2010</created_at> <text> Hello from Twitter.</text> <user> <id>2479801</id> <name>Rob Miles</name> <profile_background_image_url> http://s.twimg.com/a/1286/images/themes/theme1/bg.png </profile_background_image_url> </user></status></statuses>

Page 23: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone23

Performing the query

The first thing we need to do is get LINQ to create a LINQ XML element or XElement

We will be able to perform LINQ operations on the XElement value as if it was a database source

The Parse method works through the XML data string returned by the server

XElement TwitterElement = XElement.Parse(twitterText);

Page 24: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone24

Creating the display objects We now have an easy way that we

can use LINQ to pull the required data out of the XML feed

We want to obtain and display The text of the Twitter post The data of the post The image of the Twitter user

Once we have these values we need to display them

Page 25: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone25

Creating a display class

This the class that we will actually use to display a post on the screen

We will use Silverlight data binding to connect these properties to display elements

public class TwitterPost { public string PostText { get; set; }

public string DatePosted { get; set; }

public string UserImage { get; set; }}

Page 26: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone26

Using LINQ to create the display

This is the LINQ query that will work through the status elements in the XML and create new TwitterPost instances from each status entry

var postList = from tweet in twitterElements.Descendants("status") select new TwitterPost { UserImage = tweet.Element("user"). Element("profile_image_url").Value, PostText = tweet.Element("text").Value, DatePosted = tweet.Element("created_at").Value };

Page 27: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone27

Using LINQ to create the display

There is no restriction part as we want all the status elements

We could add one if we wanted to select particular ones based on a criteria

var postList = from tweet in twitterElements.Descendants("status") select new TwitterPost { UserImage = tweet.Element("user"). Element("profile_image_url").Value, PostText = tweet.Element("text").Value, DatePosted = tweet.Element("created_at").Value };

Page 28: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone28

Finding XML elements

The Element method locates an element with a particular name

It can be used on the element it returns This is how we get the profile image

var postList = from tweet in twitterElements.Descendants("status") select new TwitterPost { UserImage = tweet.Element("user"). Element("profile_image_url").Value, PostText = tweet.Element("text").Value, DatePosted = tweet.Element("created_at").Value };

Page 29: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone29

The postList variable The postList variable is a var type

This means that it will be set to the result of an operation that will build the type when it is used

In fact postList refers to a list of TwitterPost values

Now we need to get that list onto the Phone display

Page 30: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone30

XAML templates What we really want to do is bind our

list of Twitter posts to some kind of list on the phone

It turns out that this is very easy to do

We can create a list template that describes the layout of some Silverlight elements that can be bound to properties in the TwitterPost class

Page 31: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone31

What the display will look like

I want each twitter post to look like this

A picture on the left hand side, with the post date and content arranged to the right of this

We can use the Silverlight StackPanel element to lay this out for us

Page 32: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone32

Outer StackPanel

The outer stack panel lays out elements across the list element

<StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73" Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel></StackPanel>

Page 33: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone33

Horizontal Stack Panel

There are two elements in the horizontal stack panel One is the image of the Twitter user The other will contain the date and the

post text

Page 34: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone34

User Image

This is the image of the Twitter user The source property gives the url of

the image to be displayed

<StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73" Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel></StackPanel>

Page 35: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone35

Post details

The second element is another Stack Panel

This contains the post date above the post text

<StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73" Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel></StackPanel>

Page 36: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone36

Post details

This is the date posted element It binds to the DatePosted property in

a TwitterPost value

<StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73" Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel></StackPanel>

Page 37: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone37

Post text

This is the post text itself This is set to wrap around the text

area

<StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73" Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel></StackPanel>

Page 38: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone38

StackPanel A StackPanel will automatically

arrange the items that are placed within it

We have seen that we can place one StackPanel value inside another

They allow you to create layouts that position themselves automatically

Page 39: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone39

<ListBox Height="442" HorizontalAlignment="Left" Name="tweetsListBox" VerticalAlignment="Top" Width="468"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73"

Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate></ListBox>

The Complete ListBox template

Page 40: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone40

<ListBox Height="442" HorizontalAlignment="Left" Name="tweetsListBox" VerticalAlignment="Top" Width="468"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73"

Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate></ListBox>

A ListBox display template

The ListBox is called tweetsListbox

Page 41: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone41

<ListBox Height="442" HorizontalAlignment="Left" Name="tweetsListBox" VerticalAlignment="Top" Width="468"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73"

Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate></ListBox>

A ListBox display template

It contains an item template for each list item the box is going to display

Page 42: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone42

<ListBox Height="442" HorizontalAlignment="Left" Name="tweetsListBox" VerticalAlignment="Top" Width="468"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Height="132"> <Image Source="{Binding UserImage}" Height="73"

Width="73" VerticalAlignment="Top" /> <StackPanel Width="370"> <TextBlock Text="{Binding DatePosted}" Foreground="#FFC8AB14" FontSize="22" /> <TextBlock Text="{Binding PostText}" TextWrapping="Wrap" FontSize="24" /> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate></ListBox>

A ListBox display template

This is the StackPanel we created earlier

Page 43: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone43

Putting it all together Now we have a ListBox template for

the dislay that will lay out the tweets the way that we want them to appear

The next thing is to connect the ListBox to a datasource that contains a collection of TwitterPost objects for display

First we can take a look at how such a list could be made

Page 44: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone44

TwitterPost p1 = new TwitterPost{ DatePosted = "Tue Oct 12 11:57:37 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is a test post from Rob"};

TwitterPost p2 = new TwitterPost{ DatePosted = "Wed Oct 13 14:21:04 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is another test post from Rob"};

List<TwitterPost> posts = new List<TwitterPost>();posts.Add(p1);posts.Add(p2);

Displaying Lists of Tweets

Page 45: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone45

TwitterPost p1 = new TwitterPost{ DatePosted = "Tue Oct 12 11:57:37 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is a test post from Rob"};

TwitterPost p2 = new TwitterPost{ DatePosted = "Wed Oct 13 14:21:04 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is another test post from Rob"};

List<TwitterPost> posts = new List<TwitterPost>();posts.Add(p1);posts.Add(p2);

Displaying Lists of Tweets

This code creates two TwitterPost instances

Page 46: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone46

TwitterPost p1 = new TwitterPost{ DatePosted = "Tue Oct 12 11:57:37 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is a test post from Rob"};

TwitterPost p2 = new TwitterPost{ DatePosted = "Wed Oct 13 14:21:04 +0000 2010", UserImage = http://a3.twimg.com/1501/me2_normal.jpg", PostText = "This is another test post from Rob"};

List<TwitterPost> posts = new List<TwitterPost>();posts.Add(p1);posts.Add(p2);

Displaying Lists of Tweets

These are then added to a list of posts

Page 47: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone47

Binding an XML data source

This sets the ItemSource property of the tweetsListBox to the collection of posts that we just created

Data binding will do the rest for us

tweetsListBox.ItemsSource = posts;

Page 48: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone48

Binding to the twitter data

To see the posts loaded from the Twitter feed we use the list created by the LINQ query

The list will expand to fill the display and provide scrolling support if you want to view the rest of the items

tweetsListBox.ItemsSource = postList;

Page 49: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone49

Demo 1: Twitter viewer

Demo

Page 50: 3 4 private void loadButton_Click(object sender, RoutedEventArgs e) { string url = " + nameTextBox.Text

Windows Phone50

Review Web requests can return structured

data in XML format The Language Integrated Query

(LINQ) tools provide a way of converting structured data into objects

LINQ can decode an XML document and create objects with data properties

Collections of objects can be bound to Silverlight lists which contain display templates