Part 29: Filtering the Results by Keyword

Play Part 29: Filtering the Results by Keyword
Sign in to queue


Source Code:
PDF Version:

Currently, we can find all images on Flickr based on the locale of the device, however in our original "low tech mockup" design, we wanted to allow the user to filter the results by a keyword or search phrase. We'll enable that feature in this lesson.

Our game plan in this lesson ...

  1. We'll modify the layout of the MainPage.xaml to include a Topic textbox that will allow the end user to type in specific search terms to include in our search of images from Flickr.
  2. We'll then take that topic and send it to Flickr's web service. That will require that we change the code in a few places to accommodate the passing and receiving of the topic value.
  3. We'll then add the concept of radius to the app allowing us to specify the distance from the latitude and longitude for Flickr to include in it's search. I'll also refactor the code to harden it, or rather, make it impervious to accidental or malicious values that are nonsensical. We'll practice "defensive programming".


1. Edit MainPage.xaml: clean up layout, add Search text box

Generic Episode Image

Not depicted in this screenshot, I remove almost all of the boilerplate comments and the comments I've added previously.

  1. I change the number of RowDefinitions, as well as their heights. In line 39 I didn't specify a height, meaning I want the default value of *, or rather, star sizing ... " take the remaining available space". Line 40 sets the row height to Auto which means "distribute space evenly based on the size of the content that is within a column or row."
  2. We add a StackPanel as a container for the layout of our new Search bar at the bottom of the MainPage.xaml. The StackPanel contains a TextBlock and TextBox to allow for entry. The margin looks like it is missing two values, however that's simple a shortcut for writing:

Margin="-12, 0, -12, 0"

... it simply means "repeat these values".

Now, we'll need to add this notion of "Topic" throughout the entire application. We'll pass it along with the position to the SearchResults.xaml page, we'll pass it to the Flickr web service call, and so on.


2. Modify the Navigation code to pass Topic to SearchResults.xaml

Generic Episode Image

In the MainPage.xaml.cs, edit the SearchClick() method ...

  1. We are passing data in query strings ... We talked about query strings already. In this case, I'm concerned that a user may enter characters in the SearchTopic.Text that could be interpreted incorrectly. For example, using an ampersand or question mark could harm the interpretation of the query string. The UrlEncode() method can be used to encode the query-string values or even the entire URL. If characters such as blanks and punctuation are passed in an HTTP stream without encoding, they might be misinterpreted at the receiving end. URL encoding converts characters that are not allowed in a URL into character-entity equivalents. For more information about URL Encoding, check out:

    However, whenever you're working with query strings, whether in HTML or XAML, it's always a good idea to URL Encode, ESPECIALLY if what you're passing in the query string is input by the end user.
  2. In the string.Format, I add the "&topic={2}" to pass the Search Topic along to the next page, and ...
  3. Add the Url Encoded topic variable to substitute for the third position in the string.


3. Modify the Navigation code to RECEIVE the search topic in the SearchResults.xaml

First I'll create a private variable to hold the topic value I'm passing to the SearchResults.xaml page ...

Generic Episode Image


Next, I'll retrieve the topic value from the query string and save it in the new private variable ...

Generic Episode Image


While I'm here, I decide to go ahead and modify my call to the FlickrImage.GetFlickrImage() method. I'll need to pass the topic value to the GetFlickrImages() method that ultimately calls the Flickr web api. Since I've already made the latitude and longitude optional / defaulted input parameters to my method, the topic value must be passed in prior to those (unless I choose to make it optional as well ... but I've chosen not to.)

Generic Episode Image


Now that I've added the topic in the call, I need to modify the FlickrImage.GetFlickrImages() method itself:


Generic Episode Image


  1. I modify the method signature by adding the topic input parameter, and ...
  2. I pass topic to the getBaseUrl() method call. Now I'll need to modify THAT method as well ...


Generic Episode Image


  1. I modify the getBaseUrl() method signature by adding the topic input parameter
  2. I add the "text" parameter to the Flickr API call, per their list of parameters.
  3. I modify the line of code that replaces the placeholders with the actual values, adding topic at the end to be substituted into the new baseUrl string.

Now, I'm ready to test the results ... I'll search for "observatory" to limit the pics that are returned by the Flickr web service call to only those that have the term "observatory" in their description ...


Generic Episode Image


I get a list of photos back that Angel look different from the list of images I was getting back, and (b) they do all look like they have something to do specifically with the observatory as opposed to a street level view.


Generic Episode Image


However, I suppose I have no easy way to validate these results other than to perform a similar search on Flickr's own website look for similarities between the list I'm displaying in the AroundMe app and the results from their website. I'm satisfied with the results, so I'm not going to take the time to thoroughly check the results. I'll trust that it's working for now.

We've satisfied the title of this lesson by adding filtering on the results based on keywords. However, in the time that remains I want to add two improvements to our GetFlickrImages() method in the FlickImage.cs file ...


4. Adding radius and programming defensively

The two improvements:

First, I'll add the concept of radius ... the Flickr web api allows us to pass in the radius it will search.

Second, I'll add some code "defensive code" ... the phrase "defensive programming" is a thought process or approach to writing code. In this case, I'll apply that thought process to mean that I want do some checking of the query string values for latitude, longitude and topic that I'm passing from the MainPage to the Results, and I want to add double-quotes around the topic I want to pass to the Flickr API so the user can add a phrase. If you want to learn more about defensive programming from a high level, a great place to start is Wikipedia:

Let's begin by adding the notion of "radius" to our app. I'm not going to take the time to fully implement this in this series. Clint's original application that he gave me will adjust the radius we sent to Flickr based on how zoomed in or zoomed out we are in the Map control. However, I decided to leave that code out of this video series ... first, it will add a LOT of code to the application with come complicated calculations to convert map pixels to radius. Secondly, there's no way to simulate the pinch-in or pinch-out motion in the Windows Phone emulator. Perhaps once I'm finished with this series, I'll come back and add an addendum to how to tackle this scenario. So, for now, I'll merely add the feature for radius, and I'll hard-code the radius to 5 kilometers.

I'll modify the FlickrImage.cs ... specifically, I'll modify the getBaseUrl() method's signature to include a radius input parameter ... I default radius the same way I default latitude and longitude: to NaN, or rather, "Not A Number":

Generic Episode Image

I'll continue to modify the getBaseUrl() method by splitting out the line of code where I build the url that will later be used in the String.Format(). I want to test the topic, latitude, longitude and radius before adding them to the baseUrl returned from this method. In these cases, I want to only add values to the baseUrl that are valid. Therefore:

Generic Episode Image

  1. I re-work this entire section, removing about half of the string I'm constructing. Now that I've removed many of the variable parts (which I'll add back into the baseUrl in #2, #3, and #4, below), I can remove the variables I'll be replacing in the String.Format statement in line 89 and following.
  2. I add this gated check to ensure that the user typed something, anything into the Topic textbox on the MainPage.xaml. Assuming the user did in fact type something in, we'll surround it with double quotes (%22 is the ASCII encoding for double quotes) and add it to the baseUrl.
  3. I add this gated check to ensure that latitude and longitude are indeed numbers. If they are, then we'll add them in the baseUrl.
  4. I add this gated check to ensure that radius is indeed a number. If it is, I'll add it to the baseUrl.

Next, I'll modify the GetFlickrImages() method in the FlickImage.cs file:

Generic Episode Image

  1. I add radius and default it to NaN
  2. I include radius in the call to getBaseUrl()

Now, I'll modify the code in the SearchResults.xaml page that calls into the GetFlickrImages() method:

Generic Episode Image

Similar to what I did with topic a few moments ago:

  1. I create a private variable, _radius, to hold the radius value
  2. I include the _radius variable in the call to GetFlickImages()
  3. When the SearchResults.xaml page loads, I will grab the query string value "radius".

Now I need to PASS "radius" in the query string FROM MainPage.xaml TO SearchResults.xaml ... in the MainPage.xaml:

Generic Episode Image

... I merely hard-code this to 5, indicating 5 kilometers.

I test to make sure it works, and it does.

Again, I've merely hardcoded this value. Ideally, I would allow the radius to match the visible map on the MainPage.xaml. If you want to see a better implementation, take a look at Clint's original implementation.



To recap, the big take away from this lesson was how to grab values from XAML input controls, how to program defensively to make sure we check the input values to ensure they are valid, how to URL Encode whenever you pass values (especially, end user generated input values) in query strings of any kind. Along the way, we were able to expand the usability of our app by allowing the user to specify the type of images he or she is looking for.



The Discussion

  • User profile image

    I've run into a new issue related to the images displayed. All I receive for any kind of search, keyword or not, is a bunch of images in white with text in all kinds of different languages reading "This image or video is currently unavailable."

    Any ideas on what's up?

  • User profile image

    @RandomAlec: yeah, that happens depending on the image size with certain images on flickr.  At a certain point, we get past "beginner" which then will make explaining stuff at the level we want to for this series too hard. Flickr API may have a way to know what image sizes are available but I never dug that deep as it would add in another layer of complexity [see first point].

    The apps we picked were fun, real life examples that would be functional and expandable.  If you want to add in that extra layer of detection, we'd love to know how you did it!

Add Your 2 Cents