Search Bar - Suggestoin of Places (Bing Map) Windows Phone App 8.1 - windows-phone-8.1

I want to add Search to Bing Map Control in my Windows Phone app. I did not find any references on the internet
Scenario
1. When the user enters the name of the place. The List Box will open to show the suggested places
2. The User will select the a single option and the coordinates of the location or pushpin will be displayed to that particular area.
Help me Out Please

It's fairly easy to accomplish. You need an AutoSuggestBox:
<AutoSuggestBox TextChanged="AutoSuggestBox_TextChanged" SuggestionChosen="AutoSuggestBox_SuggestionChosen">
<AutoSuggestBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Address.PostCode}" />
<TextBlock Text="," />
<TextBlock Text="{Binding Path=Address.Town}" />
</StackPanel>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
And when the text changes you issue a query. Since a server request takes some time, make sure that you choose a reasonable response interval. So DO NOT issue a query if the input has just changed for one char.
private async void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
if (sender.Text.Length > 3)
{
// Build a hint point
Geopoint hintPoint = [..]; // Up to you, should reflect the current location
await this.Progressbar.ShowAsync();
sender.ItemsSource = await getMapSuggestionsAsync(sender.Text, hintPoint);
await this.Progressbar.HideAsync();
}
else {
sender.ItemsSource = new List<MapLocation> { };
}
}
}
All you need now is a method that issues your query:
public static async Task<List<MapLocation>> getMapSuggestionsAsync(String query, Geopoint hintPoint)
{
List<MapLocation> locations = new List<MapLocation>();
// Find a corresponding location
MapLocationFinderResult result = await MapLocationFinder.FindLocationsAsync(query, hintPoint, 2);
// If the query provides results, try to get the respective city name and
// a zip code or deny first.
if (result.Status != MapLocationFinderStatus.Success)
return locations;
foreach (var location in result.Locations)
{
MapLocation ml = await resolveLocationForGeopoint(location.Point);
if (ml != null)
locations.Add(ml);
}
return locations;
}
public static async Task<MapLocation> resolveLocationForGeopoint(Geopoint geopoint)
{
MapLocationFinderResult result = await MapLocationFinder.FindLocationsAtAsync(geopoint);
if (result.Status == MapLocationFinderStatus.Success)
{
if (result.Locations.Count != 0)
// Check if the result is really valid
if (result.Locations[0].Address.Town != "")
return result.Locations[0];
}
return null;
}
The rest is simple: If the user chooses a suggestion you get the coordinates out of the MapLocation and show a pushpin on your map.
This is some code I wrote to get a Zip code and the city name. But you can really change it to search for anything else..

Related

How to pass variable(&id) from one api to another to fetch corresponding data?

I want to display players stats in listview for which I am consuming this api: https://cricapi.com/api/playerStats?apikey=apikey&pid=pid
Output of above api is:
{
"pid": xxxx,
"profile": "profile description",
"imageURL": "https://www.cricapi.com/playerpic/xxxx.jpg",
pid for each player is retrieved from another api:
https://cricapi.com/api/playerFinder?apikey=apikey&name=playerName
Output of above api is:
{
"data": [
{
"pid": xxxx,
"fullName": "Firstname Lastname",
Currently, I am passing hardcoded pid in first api to display player's stats and code for it is:
FetchJson() async {
var response = await http.get(
'https://cricapi.com/api/playerStats?apikey=apikey&pid=1111');
if (response.statusCode == 200) {
String responseBody = response.body;
var responseJson = jsonDecode(responseBody);
pid = responseJson['pid'];
name = responseJson['name'];
playingRole = responseJson['playingRole'];
battingStyle = responseJson['battingStyle'];
country = responseJson['country'];
imageURL = responseJson['imageURL'];
data = responseJson;
var stats = data['data']['batting'];
var testStats = stats['tests'];
var odiStats = stats['ODIs'];
var tStats = stats['T20Is'];
// T20 Stats
matches_t = tStats['Mat'];
runs_t = tStats['Runs'];
half_t = tStats['50'];
century_t = tStats['100'];
highest_t = tStats['HS'];
avg_t = tStats['Ave'];
And I am calling FetchJson() inside initState().
I tried solution given on my similar / earlier question How to fetch api data by passing variables (parameters)?, but that led me to a different path. I cannot implement that solution, since there's no way for me to return pid through first api that will be received by FetchJson().
My question is:
How to retrieve pid from second api (playerFinder) and feed it to first api (playerStats) and how to make use of that pid so that instead of passing hardcoded pid, I can pass pid as variable and can display multiple players stats in UI?
Required code is here : https://pastebin.com/iU8x9U8z
I want to show players stats in UI but currently I am passing hardcoded playerid which is showing me only one player's stats, but I would like to show different players stats.
**********UPDATE *************
As an alternate solution, I am now using list of pids and parsed those using map and passing them to FetchJson() inside for loop, as below:
var playerIds = [{"pid":35320},{"pid":28114},{"pid":28779},{"pid":28763},{"pid":30176},{"pid":7133},{"pid":5390}]
#override
void initState() {
var intIds = playerIds.map<int>((m) => m['pid'] as int).toList();
for (int i = 0; i < intIds.length; i++) {
FetchJson(intIds[i]);
}
}
FetchJson(int ids) async {
print(ids);
var response = await http.get(
'https://cricapi.com/api/playerStats?apikey=apikey&pid=$ids');
....
}
The issue I am now facing with this approach is, its taking last pid from the list and displaying its data in UI repeatedly. The expected output I want to see is: players data for all pids in UI and I am not sure how to achieve this.
Complete referenced code here: https://pastebin.com/kFYBfHuf
One answer is to create Maps from both sets of api's down to desirable player data then use a switch statement as written below similar to a where clause in order to identify matching data.
The big problem is that you need to identify matching data items in both api's. In my example I've assumed it may be a players name or it could be their team and team number, but there has to be something that validates you are looking at differing data points for the same player.
switch(variable_expression) {
case name = full_name: {
// statements;
}
break;
case constant_expr2: {
//statements;
}
break;
default: {
//statements;
}
break;
}

Autosuggestbox not displaying results WP8.1 Universal App

Results template in autosuggestbox are not showing and I don't know why. I'm using MVVM Light in the app. Let's go with the code :)
In the page:
<AutoSuggestBox x:Name="txtBusqueda" x:Uid="txtBusqueda"
ItemsSource="{Binding Lugares}"
Grid.Row="1" Margin="24 24 24 12"
MaxSuggestionListHeight="4" AutoMaximizeSuggestionArea="True"
TextMemberPath="Nombre"
>
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="TextChanged">
<core:InvokeCommandAction Command="{Binding ChangeTextCommand}" CommandParameter="{Binding Text, ElementName=txtBusqueda}" />
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
<AutoSuggestBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nombre}" TextWrapping="Wrap" />
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
In the VM:
private List<LugarInfo> lugares;
public List<LugarInfo> Lugares
{
get { return this.lugares; }
set
{
if (this.lugares == value) return;
this.lugares = value;
RaisePropertyChanged(() => Lugares);
}
}
public RelayCommand<string> ChangeTextCommand { get; set; }
this.ChangeTextCommand = new RelayCommand<string>(async (s) =>
{
var result = await Api.GetInfoLugares(texto);
List<LugarInfo> lugares = new List<LugarInfo>();
foreach (var lugar in result)
{
lugares.Add(new LugarInfo()
{
Id = int.Parse(lugar.Id),
Tipo = lugar.Tipo,
Nombre = lugar.Nombre
});
}
this.Lugares = lugares;
});
So, as you can see, not too much trouble.
The results are returned and assigned to the property:
The problem is results are not displayed in control as you can see in the image.
Help will be appreciated.
your Lugares property will never raise RaisePropertyChanged because in your code you are adding your objects in lugares and than assigning it to This.Lugares which in setter is same so it will not raise the property change and and UI is not updated. change your code to as follows.
var myLugares = new List<LugarInfo>();
foreach (var lugar in result)
{
myLugares.Add(new LugarInfo()
{
Id = int.Parse(lugar.Id),
Tipo = lugar.Tipo,
Nombre = lugar.Nombre
});
}
this.Lugares = myLugares;

Drag and drop reorder list box was closed

In test.xaml
<rlb:ReorderListBox
x:Name="reorderListBox"
Grid.Row="2"
Margin="12,0,12,12"
IsReorderEnabled="True"
ItemsSource="{Binding}" >
<rlb:ReorderListBox.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="12,4,12,4"
FontSize="36"
Text="{Binding Name}" />
</DataTemplate>
</rlb:ReorderListBox.ItemTemplate>
</rlb:ReorderListBox>
int Test.xaml.cs
public void loadSource()
{
try
{
var xElem = XElement.Load("Data/SourcePage.xml");
var SourceNews =
from elem in xElem.Descendants("SourceNews")
select new ProNewsApp.Object.ObjectSource
{
Name = elem.Attribute("PageName").Value
};
reorderListBox.DataContext = SourceNews.ToList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'm follow here http://reorderlistbox.codeplex.com/ and my problem is when i'm drag and drop and my app was closed ?Why it's closed when I drag item ?How do i fix it
You need to use an ObservableCollection as the source of ReorderListBox. As the ReorderListbox changes indexes when items are reordered in the Model. So, try using:
System.Collections.ObjectModel.ObservableCollection<YourPublicClass> _observableList;
_observableList = new System.Collections.ObjectModel.ObservableCollection<YourPublicClass>(SourceNews.ToList());
reorderListBox.DataContext = _observableList;
And after rearranging items you can see that they are also changed in "_observableList".

How to get the document using view in couchbase

I have a requirement wherein I have get the document from couchbase.
Following in the Map function that I am using for the same -
function (doc, meta) {
if (meta.type == "json" && doc!=null) {
emit(doc);
}
}
There is no reduce function. Also following is my java code to get the document -
List<URI> hosts = Arrays.asList(
new URI("http://<some DNS with port>/pools")
);
// Name of the Bucket to connect to
String bucket = "Test-Sessions";
// Password of the bucket (empty) string if none
String password = "";
//System.setProperty("viewmode", "development");
// Connect to the Cluster
CouchbaseClient client = new CouchbaseClient(hosts, bucket, password);
String designDoc = "sessions";
String viewName = "by_test";
View view = client.getView(designDoc, viewName);
Query query = new Query();
query.setIncludeDocs(true);
query.setKey(String.valueOf(122));
ViewResponse result = client.query(view, query);
Object object = null;
for(ViewRow row : result) {
if(null != row) {
object = row.getDocument();
}// deal with the document/data
}
System.out.println("Object" + object);
And the data that I have in couchbase is key - "122" and value - "true". But for some reason , I do not get any rows in the ViewResponse. What is going wrong can anyone help?
I don't understand what you are trying to achieve here, you are using a view to get a document by it's key? Key == 122? Why can't you just do client.get(122) ?
If you just need a list of all the keys in your bucket (of which you can use to pull back all documents via include docs) then make your function like so:
function (doc, meta) {
if (meta.type == "json") {
emit();
}
}
The key of the document is always emitted as an ID (viewRow.getId()). You don't need to emit the document, try to emit as little data as possible to keep view sizes small.
If you are needing to manipulate all the documents in your bucket be careful as the size grows, perhaps you'd need to look at pagination to cycle through the results. http://tugdualgrall.blogspot.com.es/
Also once you have the ViewResponse loop over it like so:
for(ViewRow row : result) {
row.getDocument(); // deal with the document/data
}
You don't need to be doing checks for null on the rows.

No results in Australia using Bing Maps SOAP

I'm creating an app for WP8 and i've been using the Bing Maps tutorial. However I don't get any results in Australia. Do I need to use a completely different API? geolocale contains a string such as "20.002, -150.2222" even if I change it to just "California" it gets results. What am I doing wrong?
I've tried to find answers in a lot of places but can't seem to find anything that's relevant.
try
{
searchService.SearchCompleted += new EventHandler<SearchService.SearchCompletedEventArgs>(MySearchCompleted);
SearchService.SearchRequest mySearchRequest = new SearchService.SearchRequest();
mySearchRequest.Credentials = new SearchService.Credentials();
mySearchRequest.Credentials.ApplicationId = "key";
SearchService.StructuredSearchQuery ssQuery = new SearchService.StructuredSearchQuery();
ssQuery.Keyword = "coffee";
ssQuery.Location = geolocale;
mySearchRequest.StructuredQuery = ssQuery;
searchService.SearchAsync(mySearchRequest);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Coordinate 20.002, -150.2222 is in the middle of the Pacific ocean. Also, the Bing Maps SOAP services are an old legacy API. The Bing Spatial Data Services should be used.
http://msdn.microsoft.com/en-us/library/ff701734.aspx
http://rbrundritt.wordpress.com/2012/01/17/dynamically-updating-data-in-bing-maps-v7/
To use the Bing Spatial Data Services in WP8 first copy the Response, ResultSet, and Result classes from this project: http://code.msdn.microsoft.com/Augmented-Reality-with-bcb17045/sourcecode?fileId=85735&pathId=1819751232
You can then use the following code to generate your search query.
string baseURL;
//Switch between the NAVTEQ POI data sets for NA and EU based on where the user is.
if (Longitude < -30)
{
//Use the NAVTEQ NA data source: http://msdn.microsoft.com/en-us/library/hh478192.aspx
baseURL = "http://spatial.virtualearth.net/REST/v1/data/f22876ec257b474b82fe2ffcb8393150/NavteqNA/NavteqPOIs";
}
else
{
//Use the NAVTEQ EU data source: http://msdn.microsoft.com/en-us/library/hh478193.aspx
baseURL = "http://spatial.virtualearth.net/REST/v1/data/c2ae584bbccc4916a0acf75d1e6947b4/NavteqEU/NavteqPOIs";
}
//Search radius should be converted from meters to KM.
string poiRequest = string.Format("{0}?spatialFilter=nearby({1:N5},{2:N5},{3:N2})&$format=json&$top={4}&key={5}",
baseURL, Latitude, Longitude, SearchRadius / 1000, MaxResultsPerQuery, BingMapsKey);
You will need a method to pass this query to and serialize the results. Use the following:
private void GetResponse(Uri uri, Action<Response> callback)
{
System.Net.WebClient client = new System.Net.WebClient();
client.OpenReadCompleted += (s, a) =>
{
try
{
using (var stream = a.Result)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
if (callback != null)
{
callback(ser.ReadObject(stream) as Response);
}
}
}
catch (Exception e)
{
if (callback != null)
{
callback(null);
}
}
};
client.OpenReadAsync(uri);
}
Finally you will need to call the GetResponse method to make your query like this:
GetResponse(new Uri(poiRequest), (response) =>
{
if (response != null &&
response.ResultSet != null &&
response.ResultSet.Results != null &&
response.ResultSet.Results.Length > 0)
{
//Do something with the results
}
});