Bing Maps foreach item in list add new pushpin - c#

I'm trying to add multiple pushpins from a list to Bing Maps on Windows Phone. The name of each pushpin needs to be different, because I want to be able to remove them individually later using MainMap.Children.Remove(SpecificPushpin);.
This is my foreach:
Pushpin pushpin = new Pushpin();
Attractions attractions = new Attractions();
foreach (var attraction in Attractions.allAttractions)
{
pushpin.GeoCoordinate = new GeoCoordinate(attraction.Latitude, attraction.Longtitude);
pushpin.Content = attraction.Title;
pushpin.Background = new SolidColorBrush(Colors.Blue);
pushpin.Foreground = new SolidColorBrush(Colors.White);
MainMap.Children.Add(pushpin);
}
Of course, I receive an error after the first loop through the foreach on the MainMap.Children.Add(pushpin); line, because "pushpin" is already an existing name.
I also tried using this:
MainMap.Children.Add(new Pushpin() { Content = attraction.Title, GeoCoordinate = new GeoCoordinate(attraction.Latitude, attraction.Longtitude), Background = new SolidColorBrush(Colors.Yellow), Foreground = new SolidColorBrush(Colors.Black) });
But then I will never be able to romove the pushpins individualy.
Does anyone know how I can give a variable name to each pushpin in my list, or knows another way to fix my problem?

Instead of using Bing Maps, I used the Map Control and worked with MapLayers and MapOverlay. I created a different MapLayer for each list class and removed those individually.
This made it possible to remove one list of pushpins simply. Here's an example:
private void LoadAttractions()
{
if (cbxAttractions.IsChecked != false)
{
Attractions attractions = new Attractions();
foreach (var attraction in Attractions.allAttractions)
{
Pushpin pushpin = new Pushpin();
pushpin.Name = attraction.Title;
pushpin.GeoCoordinate = new GeoCoordinate(attraction.Latitude, attraction.Longtitude);
pushpin.Content = attraction.Title;
pushpin.Background = new SolidColorBrush(Colors.Yellow);
pushpin.Foreground = new SolidColorBrush(Colors.Black);
MapOverlay MyOverlay = new MapOverlay();
mapLayerAttractions.Add(MyOverlay);
MyOverlay.Content = pushpin;
MyOverlay.GeoCoordinate = new GeoCoordinate(attraction.Latitude, attraction.Longtitude);
MyOverlay.PositionOrigin = new Point(0.0, 1.0);
}
MainMap.Layers.Add(mapLayerAttractions);
}
}
And when cbxAttractions is being tapped:
private void cbxAttractions_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
if (cbxAttractions.IsChecked == false)
{
MainMap.Layers.Remove(mapLayerAttractions);
}
else
{
LoadAttractions();
}
}

You can give each your Pushpin a property, for example:Tag. And Each tag is not same to another. So when you remove a specific pushpin. You can use foreach like this:
foreach(PushPin pushpin in yourPushpinList)
{
if (pushpin.Tag == yourValue)
{
MainMap.Children.Remove(SpecificPushpin);
break;
}
}
the code maybe not correct, it is just a example.

Related

Adding a ListView on top of MapView in Xamarin Android using C# (Not Xml)

What I'm trying to do is writing the Xamarin Android code for the attached image (Which is Xamarin iOS)
As we can see in the attached Image, we have a UITableView with floor numbers (1, 2 and 3).
How can I add a ListView in Android using C# (Not XML) to have the same result?
Here's a code snippet of the code I'm using.
But the problem is that my ListView is always under the SearchBox which is not what I want. I want the ListView to be at the bottom of my screen.
private void CreateLayout()
{
// Create a new vertical layout for the app
var layout = new LinearLayout(this) { Orientation = Orientation.Vertical };
// Search Bar
_mySearchBox = new AutoCompleteTextView(this) { Hint = "Search rooms or people..." };
layout.AddView(_mySearchBox);
//Auto Complete Drop Down List View
_searchListView = new ListView(this);
layout.AddView(_searchListView);
// Progress bar
_myProgressBar = new ProgressBar(this) { Indeterminate = true, Visibility = ViewStates.Gone };
layout.AddView(_myProgressBar);
// Floors List View
_floorsTableView = new ListView(this);
_floorsTableView.LayoutParameters = new ViewGroup.LayoutParams(100, 150);
_floorsTableView.TextAlignment = TextAlignment.Center;
var adap = new ArrayAdapter(this, Resource.Layout.SimpleSpinnerItem, new List<string>() { "1", "2", "3" });
_floorsTableView.Adapter = adap;
_floorsTableView.Visibility = ViewStates.Visible;
layout.AddView(_floorsTableView);
// Add a map view to the layout
_myMapView = new MapView(this);
layout.AddView(_myMapView);
// Show the layout in the app
SetContentView(layout);
}
I suggest you switch to a RelativeLayout instead of using a LinearLayout to host your views. LinearLayout inherently wants to position stuff according to its orientation, while RelativeLayout gives you more freedom and power to arrange views.
Also keep in mind that the order you add views to your host container matters. So in your case I would add the ListView last. This way you will ensure that the list draws on top of anything else.
Also you need to fully specify LayoutParams for each view!
var root = new RelativeLayout(this);
_mySearchBox = new AutoCompleteTextView(this) { Hint = "Search rooms or people..." };
_myMapView = new MapView(this)
{
Id = View.GenerateViewId()
};
_floorsTableView = new ListView(this)
{
Id = View.GenerateViewId()
};
var searchBoxParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
searchBoxParams.AddRule(LayoutRules.AlignParentTop);
var mapParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
var listParams = new RelativeLayout.LayoutParams(100, 150);
listParams.AddRule(LayoutRules.AlignParentStart);
listParams.AddRule(LayoutRules.AlignParentBottom);
listParams.SetMargins(16, 0, 0, 16);
root.AddView(_myMapView, mapParams);
root.AddView(_mySearchBox, searchBoxParams);
root.AddView(_floorsTableView, listParams);
SetContentView(root, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent));
You will also want to convert the dimensions to px from dp:
private int DpToPx(int dp)
{
return (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, dp, Resources.DisplayMetrics);
}
This way your dimensions will scale according to display density.
You should use RelativeLayout to put an object over another object, then use RelativeLayout.LayoutParams to specify where you want it. So you need:
var layout = new RelativeLayout(this);
And then using LayoutRules.AlignParentBottom and LayoutRules.AlignParentLeft:
// Floors List View
_floorsTableView = new ListView(this);
// Create parameters for the listview
RelativeLayout.LayoutParams parameters = new RelativeLayout.LayoutParams(100, 150);
parameters.AddRule(LayoutRules.AlignParentBottom);
parameters.AddRule(LayoutRules.AlignParentLeft);
_floorsTableView.TextAlignment = TextAlignment.Center;
var adap = new ArrayAdapter(this, Resource.Layout.SimpleSpinnerItem, new List<string>() { "1", "2", "3" });
_floorsTableView.Adapter = adap;
_floorsTableView.Visibility = ViewStates.Visible;
// Add the listview to the layout with parameters specified
layout.AddView(_floorsTableView, parameters);
I didn't test it so you may have to play with width and height layout parameters or such.

Navigation null geocoordinate

I am totally beginner and I need some help, I am doing my application for Windows Phone 8 and I have problem with navigate to item, is like guide for example from shopping to show in item information and maps. I use web server to put all my data there and is connected with my application. Is looking for my actual position but is null with navigateitem and it can't go to another xaml because of it (itempage).
public ItemPage()
{
InitializeComponent();
this.DataContext = Globals.NavigationItem;
MapOverlay overlay = new MapOverlay();
overlay.Content = new Pushpin() { Background = new SolidColorBrush(Colors.Green) }; ;
overlay.GeoCoordinate = Globals.MyPosition;
MapOverlay itemoverlay = new MapOverlay();
itemoverlay.Content = new Pushpin() { Background = new SolidColorBrush(Colors.Blue) };
itemoverlay.GeoCoordinate = new GeoCoordinate(double.Parse(Globals.NavigationItem.Latitude), double.Parse(Globals.NavigationItem.Longitude));
MapLayer layer = new MapLayer();
layer.Add(overlay);
Mymap.Layers.Add(layer);
MapLayer itemlayer = new MapLayer();
itemlayer.Add(itemoverlay);
Mymap.Layers.Add(itemlayer);
Mymap.Center = new GeoCoordinate(double.Parse(Globals.NavigationItem.Latitude), double.Parse(Globals.NavigationItem.Longitude));
Mymap.ZoomLevel = 15;
}
The actual position is working well
private void GetUserLocation()
{
GeoCoordinateWatcher geo = new GeoCoordinateWatcher();
geo.PositionChanged += (x, y) =>
{
Globals.MyPosition = y.Position.Location;
};
geo.Start();
}
And this is navigate from shopping xaml to item xaml
private void Grid_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Globals.NavigationItem = (sender as Grid).DataContext as Item;
NavigationService.Navigate(new Uri("/Views/ItemPage.xaml", UriKind.RelativeOrAbsolute));
}
I am sorry maybe question is stupid but liked I said in the beginning I am totally beginner, hope somebody can help me :)
=>
I was wondering maybe here is some mistake because the actual location is good, server is working because took the data and put
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
client.GetZakupyAsync();
client.GetZakupyCompleted += (x, y) =>
{
if (Globals.MyPosition != null)
{
ZakupyBox.ItemsSource = y.Result.Where(p => Globals.MyPosition.GetDistanceTo(new GeoCoordinate(double.Parse(p.Latitude), double.Parse(p.Longitude))) < 5000);
if (ZakupyBox.Items.Count == 0)
{
ZakupyBox.ItemsSource = y.Result;
}
}
else
{
ZakupyBox.ItemsSource = y.Result;
}
};
}

C# WP8.1 - Displaying a MapIcon on top of a Route when using Bing Maps

I am just playing around with bing maps at the moment. I have followed the tutorials to create routes and add mapicons etc, however I have found that a mapIcon wont show if it on the route. I have tried playing with the Z-Index property of the mapIcon, however this seemed to have little effect, as I think it only has an effect with other MapElements.
Does anyone else know a way to make this happen?
My current code for creating the route and trying to set a MapIcon on the destination is (For abit of Content MapFunctions is just a static class I've made for functons such as finding the route, get the current location etc):
private async void DrawRoute()
{
// Check if a destination has been set
if(MapFunctions.destination != null)
{
route = await MapFunctions.GetRouteAsync(MapFunctions.destination.Point);
if (route != null)
{
// Use the route to initialize a MapRouteView.
MapRouteView viewOfRoute = new MapRouteView(route.Route);
viewOfRoute.RouteColor = Colors.Yellow;
viewOfRoute.OutlineColor = Colors.Black;
// Add the new MapRouteView to the Routes collection
// of the MapControl.
MyMap.Routes.Add(viewOfRoute);
// Fit the MapControl to the route.
await MyMap.TrySetViewBoundsAsync(
route.Route.BoundingBox,
null,
Windows.UI.Xaml.Controls.Maps.MapAnimationKind.None);
AddDestinationMapElement(MapFunctions.destination.Point);
// Start timer to update the remaining time of the journey
UpdateRemainingTime_Tick(this, new Object());
dispatcherTimer.Start();
}
else
{
MessageDialog message = new MessageDialog("An error occured while trying to calculate your route. Please try again later.", "Error");
await message.ShowAsync();
}
}
}
private void AddDestinationMapElement(Geopoint dest)
{
MapIcon MapIcon1 = new MapIcon();
MapIcon1.Location = new Geopoint(new BasicGeoposition()
{
Latitude = dest.Position.Latitude,
Longitude = dest.Position.Longitude
});
MapIcon1.Visible = true;
MapIcon1.ZIndex = int.MaxValue;
MapIcon1.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Images/mapIcon.png"));
MapIcon1.NormalizedAnchorPoint = new Point(0.5, 1.0);
MapIcon1.Title = "Destination";
MyMap.MapElements.Add(MapIcon1);
}
If you want to add pushpin on top of your elements, you can use MapOverlay that will allow you to add pushpin (with image or any XAML element) into your map control:
MapOverlay pushpinStart = new MapOverlay();
pushpinStart.PositionOrigin = new Point(0.5, 0.5);
pushpinStart.Content = new Image()
{
Source =
new BitmapImage(
new Uri("../Assets/Ui/ui-pin-start.png", UriKind.Relative))
};
pushpinStart.GeoCoordinate = posCollection[0];
If you want to stay with MapIcon, then the rendering engine will calculate what's best to be displayed based on the zoom level and current location as well as other elements collision algorithm's result. So I'm not sure that what you're looking for.
And for WP8.1, here is the equivalent code:
Image iconStart = new Image();
iconStart.Source = new BitmapImage(new Uri("ms-appx:///Assets/Ui/ui-pin-start.png"));
this.Map.Children.Add(iconStart);
MapControl.SetLocation(iconStart, new Geopoint(pos[0]));
MapControl.SetNormalizedAnchorPoint(iconStart, new Point(0.5, 0.5));

Windows 8 Secondary Tile using Templates

I have a windows store app that currently allows my users to pin and unpin tiles to the start menu. I am able to set a background and logo and text but the problem is I want the tile to instead of a static logo with text I want it to be sort of a live tile.
So it would go from one side with just an image and then flip and the other side would be my app information. I know you are able to do this for regular live tiles and using xml, but I am using c# and would like for this to work in my secondary tile.
Any help on how to go about that would be great.
Here is some code I used to create the secondary tile:
private async void PinButton_OnClick (object sender, RoutedEventArgs e)
{
var item = createdItem.SelectedItem;
if (item != null)
{
var logo = new Uri(item.image);
if (item != null)
{
var smallLogo = new Uri(item.image);
var wideLogo = new Uri(item.image);
}
string tileActivationArguments = logoSecondaryTileId + "WasPinnedAt=" +
DateTime.Now.ToLocalTime();
logoSecondaryTileId = item.ID+ counter.ToString();
counter++;
//Create the tile
SecondaryTile tile = new SecondaryTile(logoSecondaryTileId, item.Code, item.FirstName + " " + item.LastName,
tileActivationArguments, TileOptions.ShowNameOnLogo | TileOptions.ShowNameOnWideLogo, logo);
if (item.SelectedItem is Details)
{
tile.ForegroundText = ForegroundText.Light;
tile.BackgroundColor = Colors.Black;
bool isPinned =
await
tile.RequestCreateForSelectionAsync(GetElementRect((FrameworkElement)sender),
Placement.Default);
if (isPinned)
{
Messages.InvokeToast(Toast.Created);
UnpinButton.Visibility = Visibility.Visible;
pinButton.Visibility = Visibility.Collapsed;
}
else
{
Messages.InvokeToast(Toast.Error);
}
if (SecondaryTile.Exists(logoSecondaryTileId))
{
var dialog = new MessageDialog("Already exists!")
{
Title = "Unable to Pin Tile!"
};
dialog.Commands.Add(new UICommand("Okay", new UICommandInvokedHandler(CommandHandler)));
dialog.CancelCommandIndex = 1;
await dialog.ShowAsync();
}
}
}
}
You just need to define the tile using a template that has a front and back. See here for how to define secondary tiles with templates: Is it possible to use tile templates with secondary tiles in a Windows Store App?. See here for the list of possible templates and which have backs: http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx

MapPolyline not being drawn

I am trying to use a MapPolyLine in my Map to show a real-time route, hopefully it will move/scale this time. The thing is the line is not being shown on the map, and I cannot find any programming mistake:
C#
MapLayer pathLayer;
//Constructor
pathLayer = new MapLayer();
MapPolyline line = new MapPolyline();
line.StrokeColor = Colors.Red;
line.StrokeThickness = 10;
//line.Path.Add(several points); Tested, no effect
MapOverlay overlay = new MapOverlay();
overlay.Content = line;
//overlay.GeoCoordinate = new GeoCoordinate(0,0); Tested, no effect
//overlay.PositionOrigin = new Point(0.0, 1.0); Tested, no effect
pathLayer.Add(overlay);
MyMap.Layers.Add(pathLayer);
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
MapPolyline line = pathLayer.First(TrackPath).Content as MapPolyline;
line.Path.Add(args.Position.Coordinate); // Checked values, line.Path adds them correctly
}
EDIT: New info. The emulator shows an error when trying to add it using XAML, and the emulator shows the name of the class on the top of the map as a graphic glitch:
MapPolylines and MapPolygons should be added to the MapElements collection... not a MapLayer or a MapOverlay.
You should be able to make this example work for you.
MapPolyline line = new MapPolyline();
line.StrokeColor = Colors.Red;
line.StrokeThickness = 10;
line.Path.Add(new GeoCoordinate(47.6602, -122.098358));
line.Path.Add(new GeoCoordinate(47.561482, -122.071544));
MyMap.MapElements.Add(line);
In your GeoCoord watcher you'll have to get the line from the map's MapElements collection, and add the new position to the line's path instead of predefining like I did. This should be doable.
In Windows Phone 8.1 try add points in this way. "punkty" is my collection.
List<BasicGeoposition> PosList = new List<BasicGeoposition>();
foreach (var item in punkty)
{
PosList.Add(new BasicGeoposition()
{
Latitude = item.Position.Latitude,
Longitude = item.Position.Longitude
});
}
//Example of one point
//PosList.Add(new BasicGeoposition()
//{
// Latitude = 52.46479093,
// Longitude = 16.91743341
//});
MapPolyline line = new MapPolyline();
line.StrokeColor = Colors.Red;
line.StrokeThickness = 5;
line.Path = new Geopath(PosList);
myMap.MapElements.Add(line);

Categories