RositsaV
RositsaV

Reputation: 101

How to add data from database into pins using xamarin.forms.maps android

I set a two new properties on Xamarin Info Window on the map and I want to fill it with data from two columns on the date base:

public MapPage()
    {
        InitializeComponent();

        DatabaseConnection();

        CustomPin pin1 = new CustomPin
        {
            Type = PinType.Place,
            Position = new Position(41.59043006333251, 24.766286971618303),
            Name = "Xamarin",
            Label = "р. Бяла",
            Address = "гр. Смолян",
            CodeNum = 1,
            AlertLevel = 2
        };

        CustomPin pin2 = new CustomPin
        {
            Type = PinType.Place,
            Position = new Position(41.56817473054596, 24.758451447799708),
            Label = "р. Черна",
            Name = "Xamarin",
            Address = "гр. Смолян",
            CodeNum = 2,
            AlertLevel = 2
        };

        customMap.CustomPins = new List<CustomPin> {
            pin1,
            pin2,
        };
        customMap.Pins.Add(pin1);
        customMap.Pins.Add(pin2);

        customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(41.567797926753485, 25.389703182725665), Distance.FromKilometers(70)));
    }

In every:

CustomPin pin1 = new CustomPin
    {
        Type = PinType.Place,
        Position = new Position(41.59043006333251, 24.766286971618303),
        Name = "Xamarin",
        Label = "р. Бяла",
        Address = "гр. Смолян",
        CodeNum = ?,
        AlertLevel = ?
    };

I have property CodeNum and AlertLevel, but I don't know how to fill this properties with the data from database.

My DatabaseConnection() method look like:

        public async void DatabaseConnection()
    {
        string ConnectionString = "server=192.168.0.3;uid=username;port=3307;pwd=password;database=ardaforecast;";
        MySqlConnection Conn = new MySqlConnection(ConnectionString);

        try
        {
            Conn.Open();
            string query = "SELECT * FROM sel_alert_level s;";
            MySqlCommand myCommand = new MySqlCommand(query, Conn);
            MySqlDataReader myReader;

            myReader = myCommand.ExecuteReader();
            try
            {
                while (myReader.Read())
                {
                    int codeNum = myReader.GetInt32(4);
                    int level = myReader.GetInt32(3);

                    //await DisplayAlert("Database Connection", "Connected .." + Environment.NewLine + myReader.GetInt32(0) + Environment.NewLine + myReader.GetString(1) + Environment.NewLine + myReader.GetString(2) + Environment.NewLine + myReader.GetInt32(3) + Environment.NewLine + myReader.GetInt32(4), "OK");
                }
            }
            finally
            {
                myReader.Close();
                Conn.Close();
            }
        }

        catch (Exception ex)
        {
            await DisplayAlert("Database Connection", "Not Connected ..." + ex.ToString(), "OK");
        }
    }

When I set DisplayAlert in the while loop I see all my records, but I need only codeNum and level to set on the every pin ?

I have 17 pins with 17 records on these two columns codeNum and level.

This is my CustomMapRenderer.cs file:

    using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using CustomRenderer;
using CustomRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
    {
        List<CustomPin> customPins;

        public CustomMapRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                NativeMap.InfoWindowClick -= OnInfoWindowClick;
            }

            if (e.NewElement != null)
            {
                var formsMap = (CustomMap)e.NewElement;
                customPins = formsMap.CustomPins;
            }
        }

        protected override void OnMapReady(GoogleMap map)
        {
            base.OnMapReady(map);

            NativeMap.InfoWindowClick += OnInfoWindowClick;
            NativeMap.SetInfoWindowAdapter(this);
        }

        protected override MarkerOptions CreateMarker(Pin pin)
        {
            var marker = new MarkerOptions();
            marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
            marker.SetTitle(pin.Label);
            marker.SetSnippet(pin.Address);
            marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.green));
            return marker;
        }

        void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
        {
            var customPin = GetCustomPin(e.Marker);
            if (customPin == null)
            {
                throw new Exception("Custom pin not found");
            }

            if (!string.IsNullOrWhiteSpace(customPin.Url))
            {
                var url = Android.Net.Uri.Parse(customPin.Url);
                var intent = new Intent(Intent.ActionView, url);
                intent.AddFlags(ActivityFlags.NewTask);
                Android.App.Application.Context.StartActivity(intent);
            }
        }

        public Android.Views.View GetInfoContents(Marker marker)
        {
            var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;
            if (inflater != null)
            {
                Android.Views.View view;

                var customPin = GetCustomPin(marker);
                if (customPin == null)
                {
                    throw new Exception("Custom pin not found");
                }

                if (customPin.Name.Equals("Xamarin"))
                {
                    view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
                }
                else
                {
                    view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
                }

                CustomPin pin = GetCustomPin(marker);

                int CodeNum = pin.CodeNum;          
                int AlertLevel = pin.AlertLevel;

                var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
                var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
                var infoSubtitle2 = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle2);
                var infoSubtitle3 = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle3);

                if (infoTitle != null)
                {
                    infoTitle.Text = marker.Title;
                }
                if (infoSubtitle != null)
                {
                    infoSubtitle.Text = marker.Snippet;
                }
                if (infoSubtitle2 != null)
                {
                    infoSubtitle2.Text = "Тревога: (1-4): " + AlertLevel;
                }
                if (infoSubtitle3 != null)
                {
                    infoSubtitle3.Text = "Номер на станция: " + CodeNum;
                }

                return view;
            }
            return null;
        }

        public Android.Views.View GetInfoWindow(Marker marker)
        {
            return null;
        }

        CustomPin GetCustomPin(Marker annotation)
        {
            var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
            foreach (var pin in customPins)
            {
                if (pin.Position == position)
                {
                    return pin;
                }
            }
            return null;
        }
    }
}

How can I fill my pins with this records ?

Upvotes: 0

Views: 197

Answers (1)

Jason
Jason

Reputation: 89102

create a dictionary to store your db data in

Dictionary<int,int> dbdata = new Dictionary<int,int>();

then populate it

while (myReader.Read())
{
    int codeNum = myReader.GetInt32(4);
    int level = myReader.GetInt32(3);

    dbdata.Add(codeNum,level);
}

then when you build each Pin get the AlertLevel value from the dictionary

CustomPin pin2 = new CustomPin
    {
        Type = PinType.Place,
        Position = new Position(41.56817473054596, 24.758451447799708),
        Label = "р. Черна",
        Name = "Xamarin",
        Address = "гр. Смолян",
        CodeNum = 2,
        AlertLevel = dbdata[2]
    };

Upvotes: 1

Related Questions