silverlight etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
silverlight etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

21 Kasım 2010

Windows Phone 'da Silverlight Bing Map Kullanımı

Merhaba, bu yazımızda Windows Phone 7 cihazımızda (emulator ile) 'Silverlight Bing Map' i incelemeye çalışacağız. Uygulamalarımızda oldukça sık ihtiyaç duyulabilecek harita üzerinde yer göstermek, bu yere raptiye (pushpin) ekleyerek belirtmek ve belirttiğimiz yer üzerine bir not düşmek, belirli bir noktadan, bir diğer noktaya yolun rotasını gösterebilmek gibi konular için bing map bulunmaz bir araç.

Örnek bir uygulama geliştirmeden önce, bir takım ön hazırlıklar yapmamız gerekiyor. İşe Bing Map Sdk'yı bilgisayarımıza kurarak başlayabiliriz. Tabii bu sdk'dan da önce pc'mizde VS 2010 ve phone developer tools'un kurulu olduğunu varsayalım.

Bing Map Silverlight Control SDK'yı buradan indirebilirsiniz. Bing Map'i çok daha yakından, silverlight (xaml ve cs) örnek source kodlarıyla birlikte incelemek isteyenler de buradan (Interactive SDK) erişebilirler.

Bilgisayarımıza map sdk'yı da kurduğumuzu varsaydıktan sonra, şimdi de sıra MS Live acount'umuzu kullanarak bir bing map ID'si almaya geldi. Bunun için microsoft'un Maps Account Center portal adresine gitmemiz gerekiyor. Accout adrese buradan (http://www.bingmapsportal.com/) erişilebilir.

Maps Accout Portal'a gittiğimizde ise karşımıza şöyle bir ekran görüntüsü çıkacaktır;


Live account'umuzu kullanarak giriş yaptıktan (Sign In) sonra, Create or view keys linki kullanarak, yeni bir bing map ID (ya da Key) oluşturabilir veya görüntüleyebiliriz. Key oluşturduğumuzda veya görüntülediğimizde aşağıdaki gibi bir ekran görüntüsü ile karşılaşacağız.
Portal'dan bir Key'de elde ettiğimize göre şimdi örnek uygulamamızı geliştirmeye başlayabiliriz. Öncelikle VS 2010 / File / New Project / Silverlight for Windows Phone template ile yeni bir proje oluşturalım. Oluşturduğumuz projemize defaul olarak MainPage.xaml ve App.xaml gelmektedir.

App.xaml dosyası cs editörümüzü açarak aşağıdaki gibi bing map portal'dan elde ettiğimiz Key'imizi Id adıyla diğer sayfalardan erişilebilecek şekilde tanımlayalım.

public partial class App : Application {

internal const string Id = "";

Sdk kurulumundan sonra aşağıdaki resimde de görüleceği gibi pek çok kontrolün eklendiğini göreceğiz.



Şimdi MainPage.xaml Grid içerisine silverlight bing map sdk ile birlikte gelen Map kontrolümüzü aşağıdaki gibi ekleyelim. Xaml kodlarından da görüleceği gibi copright ve logo'yu görünmez hale getirmemiz de mümkün.

MainPage.xaml

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

Grid.RowDefinitions>

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="Enlem : Boylam" FontSize="26"/>

<TextBlock x:Name="PageTitle" Text="Lat. : Long. " FontSize="22" />

StackPanel>

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Microsoft_Phone_Controls_Maps:Map

x:Name="myMap"

d:LayoutOverrides="Width, Height"

CopyrightVisibility="Collapsed"

LogoVisibility="Collapsed"

TargetViewChanged="myMap_TargetViewChanged">

<Microsoft_Phone_Controls_Maps:Map.Mode>

<Microsoft_Phone_Controls_Maps:AerialMode ShouldDisplayLabels="True" />

Microsoft_Phone_Controls_Maps:Map.Mode>

Microsoft_Phone_Controls_Maps:Map>

Grid>

Grid>

<phone:PhoneApplicationPage.ApplicationBar>

<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">

<shell:ApplicationBarIconButton IconUri="/icons/reload_alt1_18x21.png" Text="Change Map Mode" Click="btnChangeMode_Click"/>

<shell:ApplicationBarIconButton IconUri="/icons/plus_alt_32x32.png" Text="Zoom In" x:Name="btnZoomIn" Click="btnZoomIn_Click" />

<shell:ApplicationBarIconButton IconUri="/icons/minus_24x6.png" Text="Zoom Out" x:Name="btnZoomOut" Click="btnZoomOut_Click"/>

<shell:ApplicationBarIconButton IconUri="/icons/home_24x24.png" Text="Home" x:Name="btnCenter" Click="btnCenter_Click"/>

shell:ApplicationBar>

phone:PhoneApplicationPage.ApplicationBar>


MainPage.cs sınıfımıza map kontrol yüklendiğinde default zoomlevel (yükseklik) , bing map portal'dan elde ettiğimiz Key'i tanımlayacağımız CredentialsProvider nesnemizi ve haritamızın ekranda görüleceği ilk konumu private olarak tanımlayalım.

Pushpin myPushpin_1 = new Pushpin();

myPushpin_1.Location = new GeoCoordinate(38.3744951212275, 26.8655549034000);

myPushpin_1.Content = "Günlük taze balık alınabilir..";

myPushpin_1.Background = new SolidColorBrush(Colors.Red);

MainPage.cs sınıfımızın son halini de aşağıdaki gibi tamamlayalım.

C#

public partial class MainPage : PhoneApplicationPage {

private const double DefaultZoomLevel = 17.0;

private readonly CredentialsProvider _credentialsProvider = new ApplicationIdCredentialsProvider(App.Id);

private static readonly GeoCoordinate DefaultLocation = new GeoCoordinate(38.3744951212275, 26.8655549034000);

public MainPage() {

InitializeComponent();

Loaded += MainPage_Loaded;

}

private void MainPage_Loaded(object sender, RoutedEventArgs e) {

myMap.CredentialsProvider = _credentialsProvider;

Pushpin myPushpin_1 = new Pushpin();

myPushpin_1.Location = new GeoCoordinate(38.3744951212275, 26.8655549034000);

myPushpin_1.Content = "Günlük taze balık alınabilir..";

myPushpin_1.Background = new SolidColorBrush(Colors.Red);

myMap.Children.Add(myPushpin_1);

myMap.Center = DefaultLocation;

myMap.ZoomLevel = DefaultZoomLevel;

}

private void changeMapMode() {

if (myMap.Mode is AerialMode) {

myMap.Mode = new RoadMode();

}

else {

myMap.Mode = new AerialMode(true);

}

}

private void btnChangeMode_Click(object sender, EventArgs e) {

changeMapMode();

}

private void btnZoomIn_Click(object sender, EventArgs e) {

myMap.ZoomLevel = myMap.ZoomLevel + 1;

}

private void btnZoomOut_Click(object sender, EventArgs e) {

myMap.ZoomLevel = myMap.ZoomLevel - 1;

}

private void btnCenter_Click(object sender, EventArgs e) {

myMap.Center = DefaultLocation;

myMap.ZoomLevel = DefaultZoomLevel;

}

private void myMap_TargetViewChanged(object sender, MapEventArgs e) {

// Enlem ve Boylam

PageTitle.Text = string.Format("{0} : {1}", myMap.Mode.TargetCenter.Latitude, myMap.Mode.TargetCenter.Longitude);

}

}

ZoomIn, ZoomOut, Map Mode ve Map Center özellikleri için Application Bar icon butonlarından faydalanabiliriz. Her bir icon button için o özelliğe uygun iconlar set ediyoruz.

F5 ile projemizi çalıştırarak emulatör ile haritamız üzerinde gezebiliriz. Map.Center özelliğini kullandığımız için haritamız ilk açılışında enlem ve boylam coordinatlarını verdiğimiz yere konumlanacaktır.



Haritamız üzerinde gezerken enlem ve boylam koordinat bilgilerini de aynı anda görebilmek haritamızın TargetViewChanged event'ını kullandık ve bu değerleri ekranımızın üst kısmındaki textblock'larına yazdırmış olduk.

private void myMap_TargetViewChanged(object sender, MapEventArgs e) {

// Enlem ve Boylam

PageTitle.Text = string.Format("{0} : {1}", myMap.Mode.TargetCenter.Latitude, myMap.Mode.TargetCenter.Longitude);

}

Haritamız üzerinde yapabileceklerimiz tabiki bunlarla sınırlı değil, örneğin aramak istediğimiz bir yeri adına göre arayabilir veya iki nokta arasındaki yolu (ya da rotayı) da haritamız üzerinde gösterebiliriz.

Yer arama ya da rota belirtme gibi işlemler için Bing Map'in SOAP servislerini kullanabiliriz. Bu servislerin erişim adresleri aşağıdaki gibidir. Projemiz'e service referans olarak ekledikten sonra kullanıma hazır durumda olacaktır.

http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc

http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc

http://dev.virtualearth.net/webservices/v1/searchservice/searchservice.svc

Projemize servislerimizi ekledikten sonra otomatik olarak oluşan ServiceReferences.ClientConfig configurasyon dosyasının da aşağıdaki gibi oluştuğunu göreceğiz.

<configuration>

<system.serviceModel>

<bindings>

<basicHttpBinding>

<binding name="BasicHttpBinding_IGeocodeService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

<security mode="None" />

binding>

<binding name="BasicHttpBinding_IRouteService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

<security mode="None" />

binding>

<binding name="BasicHttpBinding_ISearchService" maxBufferSize="2147483647"

maxReceivedMessageSize="2147483647">

<security mode="None" />

binding>

basicHttpBinding>

bindings>

<client>

<endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"

contract="service.geocode.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />

<endpoint address="http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRouteService"

contract="service.route.IRouteService" name="BasicHttpBinding_IRouteService" />

<endpoint address="http://dev.virtualearth.net/webservices/v1/searchservice/searchservice.svc"

binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISearchService"

contract="service.search.ISearchService" name="BasicHttpBinding_ISearchService" />

client>

system.serviceModel>

configuration>

Yukarıdaki gibi servislerimizi ekledikten sonra, örneğin iki nokta arasındaki yolu (rotayı) gösterebilmek için öncelikle GeocodeService'i kullanıp GeocodeResult nesnesini result olarak elde ettikten sonra (GeocodeResult içerisinde bulunan iki yere ait location (coordinat) bilgileri yer alacaktır) RouteService ile bu noktaların oluşturduğu rotaya harita üzerinde konumlanlanılacaktır. RouteServis çağrısı sonucunda RouteResponce nesnesi olarak geri dönecek ve RouteResponce.RoutePath içerisinde iki nokta arasındaki yolu oluşturan noktalar yer alacaktır. Noktalar elimize geçtikten sonra, bu noktalar ile MapPolyLine kontrolünü oluşturabiliriz. Oluşturduğumuz MapPolyLine kontrolünüde Map kontrolü içine ekleyerek, rotamızı harita üzerinde gösterebileceğiz.

Tabii bu servisleri de kullanabilek için Bing Map Portal'dan aldığımız Key'imizi servis request nesnelerinin, credential'ına set etmemiz gerekmektedir.

Silverlight Bing Map'in Search, Route v.s. gibi özelliklere ait tüm source code'larına aşağıdaki adresden ulaşılabileceğini bir kere daha hatırlatarak makalemizi burada sonlandıralım.( http://www.microsoft.com/maps/isdk/silverlight/#MapControlInteractiveSdk.Tutorials.Services.Route )




Kolay gelsin.

6 Haziran 2009

Silverlight ile bir WCF Servisi ve Cross Domain Access

Merhaba,
Bu yazımda bir Silverlight 2 uygulamasında, client taraf ile ASP .NET tarafı arasında veri alışverişini sağlayacak uygulama geliştirmek istediğimizde karşımıza çıkması muhtemel olan Cross Domain Restrictions (çapraz etki alanı kısıtlamaları) olayını 2 farklı yöntemle aşmaya çalışacağız.

Resim: Cross-domain erişim yapısı.

Cross Domain Restrictions’dan kısaca bahsetmek gerekirse; bir güvenlik önlemi olarak, Silverlight kendi çalışma alanı (domain) sınırları dışında çalışma izni vermemektedir.

Bu yazımızdaki örneğimizde kendi local bilgisayarımızda oluşturacağımız iki farklı domain ile konuyu ele alacağız.
Cross Domain hatasını elde edebilmek için bir WCF servisi kullanacağız. Farklı domain elde edebilmek için ise bilgisayarımızın wwwroot dizinine test isminde bir dizine domain oluşturacağız.

1. domain : http://localhost:1283 (prolemizin debug modda çalıştığı durum)
2. domain : http://localhost/test (uygulamayı publish ettiğimiz yer)

Amacımız, Silverlight uygulamamızın localhost/test etki alanından, localhost:1283'de bulunan servise erişmeye çalışmak olacak.

ASP.NET tarafında bize veri iletimini sağlaması amacıyla bir Silverlight-enabled WCF Service oluşturalım.

Solution Explorer üzerinde resimdeki gibi bir Silverlight uygulaması üzerinde çalıştığımızı varsayalım.
Server taraftaki (ASP.NET tarafı) SilverWebServiceTestProj.Web projesi üzerine sağ tıklayarak Add New Item penceresinden Silverlight-enabled WCF Service ekleyelim.

Hemen ardından web servisimize artık gelenekselleşmiş olan, standart mesajımız “Hello World” mesajını ekliyoruz. Buradaki amacımız WCF servis yapısını anlatmak olmadığından bu kısımları hızlıca geçiyoruz.
[OperationContract]
public string HelloWorld()
{
return "Hello World";
}

Uygulamamızın Client tarafına ServiceReferance isimli WCF servis referansımızı ekleyelim. ServiceReferance.ClientConfig isimli configurasyon dosyası da projemize eklenecektir.

ServiceReferance.ClientConfig dosyasının içeriğine göz atalım. Endpoint address’in localhost 1283 no’lu port dan çalışacak şekilde otomatik olarak yazıldığı görülecektir.




Şimdi de Page.xaml.cs içine yazacağımız c# kodlarını oluşturalım. Page loaded event’ı çalıştığında ekrana “Hello World” mesajımızı yazdıracağız.

public partial class Page : UserControl
{
private ServiceReferance.Service1Client myService = null;
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
myService = new SilverWebServiceTestProj.ServiceReferance.Service1Client();
myService.HelloWorldCompleted += myService_HelloWorldCompleted;
myService.HelloWorldAsync();
}
private void myService_HelloWorldCompleted(object sender, SilverWebServiceTestProj.ServiceReferance.HelloWorldCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show(e.Result);
}
else {

MessageBox.Show(e.Error.Message);
}
} }

Page.xaml’a hiçbir kod satırı eklemeden F5 ile debug modda projemizi derleyip çalıştırdığımızda herhangi bir hata ile karşılaşmadan “Hello World” mesajı ile karşılaşacağız.
Şimdi uygulamamızı faklı bir etki alanına (localhost/test) publish edelim ve localhost:1283 adresinde bulunan WCF servisimize erişmeye çalışalım.


ASP .NET projemize sağ tıklayarak Publish seçeneğini seçelim. Local makinemizde oluşturacağımız test isimli dizine publish ediyoruz. (wwwroot/test)

Publish işlemi tamamlandıktan sonra yeni bir browser açarak uygulamızı çalıştıralım.
Uygulama adresini yazıp çalıştırdığımızda aşağıdaki cross domain hatası ile karşılaşacağız.

Alınan Hata Mesajı: "An error occured while tyring to make a request to URI http: //localhost:1283/Service1.svc. This could be due to attemting to access a service in a cross-domain way without a proper cross domain policy in place, ..." şeklinde uzayıp giden bir hata mesajı.
Yukarıdaki hatayı almamızın sebebi, localhost/test etki alanından, localhost:1283 etki alanında bulunan WCF servisine erişmeye çalışmamızdır. Bu hatayı almamız son derece normal.

Buradaki hatayı almamak için 2 farklı yöntem ele alacağız.
İlk yöntemimiz de erişmeye çalışacağımız etki alanının çağrımıza izin vermesi. Bunun için Server taraftaki projemize clientaccesspolicy.xml isimli dosyayı ekleyelim. İçeriğini aşağıdaki gibi hazırlayalım.

clientaccesspolicy.xml












İstemciden gelen bir çağrı durumunda, clientaccesspolicy.xml dosyası eğer var ise, bu dosyadaki içeriğe göre gelen çağrıya izin verilir ya da verilmez. Clientaccesspolicy.xml dosyasını özelleştirerek yalnızca belirli alan adlarının erişmesini de sağlayabiliriz. Bu dosya hakkındaki detay bilgilere buradan erişilebilir.














İkinci yöntemimiz, client uygulamamızın çağrıda bulunmadan önce erişmek isteyeceğimiz WCF servisin etki alanını önceden bilmesi durumudur. Öncelikle bu etki alanını elde edip yeni bir http binding oluşturacağız ve ardından servis referansımızı da yeniden oluşturup çağrıda bulunacağız.

Ele alacağımız örneğimizde farklı bir domain'e geçmeden içinde bulunduğumuz domain'i konrol ederek kendi domain yapımız içinde yer alan servise erişmiş olalım. Böylelikle uygulamamız içinde kullandığımız servisleri her hangi bir IIS' e publish ederken de farklı bir domain de olup olmaması gibi bir problemle de karşılaşmayız.
Aşağıdaki örnek c# kodunu farklı domain'de bulunan bir servis için de gerçekleştirebiliriz.
Artık sözü c#'a bırakalım.
public partial class Page : UserControl
{
private ServiceReferance.Service1Client myService = null;
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{

int lastIndex = HtmlPage.Document.DocumentUri.AbsoluteUri.LastIndexOf("/");
string basePath = HtmlPage.Document.DocumentUri.AbsoluteUri.Substring(0, lastIndex);
string serviceAddress = string.Concat(basePath, "/Service1.svc");

myService =
new SilverWebServiceTestProj.ServiceReferance.Service1Client(new BasicHttpBinding(),
new EndpointAddress(serviceAddress));
myService.HelloWorldCompleted += myService_HelloWorldCompleted;
myService.HelloWorldAsync();
}
private void myService_HelloWorldCompleted(object sender, SilverWebServiceTestProj.ServiceReferance.HelloWorldCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show(e.Result);
}
else {
MessageBox.Show(e.Error.Message);
} } }
Kolay gelsin.
Kaynak: