Longlistselector | Engin Polat\'ın Windows 8 , Windows Phone 8 ve C# içerikli programcılık sitesi

Arşiv

Etiketlenen yazılar longlistselector

Windows Phone için Bing arama uygulaması

02 August 2013 1 yorum

Windows Phone uygulamamıza internetten arama özelliği eklememiz gerektiği durumda, Bing arama motorunun API desteği olduğu için bunu yapabilmemiz çok zor olmayacaktır.

Windows Azure Markeplace üzerinden erişebileceğiniz Bing Search API – Web Results Only API sayfasından Bing Web Search API kullanım bilgilerine erişebiliriz, gerekli yetkiyi alabiliriz.

İlk olarak Sign In linkine tıklayarak oturum açalım ve aylık 5000 aramayı ücretsiz yapabilmemize olanak sağlayacak Sign Up butonuna tıklayarak gerekli yetkiyi alalım.

Sign Up butonuna tıkladığınızda ekrana sözleşme şartlarını kabul etmenizi sağlayacak bir ekran gelecek. Basitçe ileri-ileri diyerek geçebileceğiniz ekranlardan sonra aylık 5000 aramayı ücretsiz yapabileceğiniz yetkiyi almış olacaksınız.

Gelelim Windows Phone 8 projemize;

MainPage.xaml dosyasını açarak tasarımı aşağıdaki gibi olacak şekilde değiştirelim;

<phone:PhoneApplicationPage
	x:Class="BingSearchSample.MainPage"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
	xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	mc:Ignorable="d"
	FontFamily="{StaticResource PhoneFontFamilyNormal}"
	FontSize="{StaticResource PhoneFontSizeNormal}"
	Foreground="{StaticResource PhoneForegroundBrush}"
	SupportedOrientations="Portrait" Orientation="Portrait"
	shell:SystemTray.IsVisible="True">

	<StackPanel>
		<StackPanel Orientation="Horizontal" Margin="10,0,0,0">
			<Image Source="/Assets/bing-logo.png" Width="120" Height="45" />
			<TextBox Name="SearchKey" Width="350" InputScope="Search" KeyUp="SearchKey_OnKeyUp" />
		</StackPanel>

		<phone:LongListSelector Name="SearchResultList" Height="655" SelectionChanged="SearchResultList_OnSelectionChanged">
			<phone:LongListSelector.ItemTemplate>
				<DataTemplate>
					<StackPanel Margin="0,0,0,30">
						<TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextTitle2Style}" />
						<TextBlock Text="{Binding Description}" Style="{StaticResource PhoneTextSmallStyle}" TextWrapping="Wrap" />
						<TextBlock Text="{Binding DisplayUrl}" Style="{StaticResource PhoneTextAccentStyle}" />
					</StackPanel>
				</DataTemplate>
			</phone:LongListSelector.ItemTemplate>
		</phone:LongListSelector>
	</StackPanel>

	<phone:PhoneApplicationPage.ApplicationBar>
		<shell:ApplicationBar>
			<shell:ApplicationBarIconButton IconUri="/Assets/feature.search.png" Text="ara" Click="SearchButton_OnClick"></shell:ApplicationBarIconButton>
		</shell:ApplicationBar>
	</phone:PhoneApplicationPage.ApplicationBar>

</phone:PhoneApplicationPage>

Bir StackPanel içerisine Bing logosu ve arama kelimesinin girileceği TextBox nesnesini ekliyoruz;

<StackPanel Orientation="Horizontal" Margin="10,0,0,0">
	<Image Source="/Assets/bing-logo.png" Width="120" Height="45" />
	<TextBox Name="SearchKey" Width="350" InputScope="Search" KeyUp="SearchKey_OnKeyUp" />
</StackPanel>

SearchKey isimli TextBox nesnesinin InputScope özelliğine Search değerini veriyoruz, böylece TextBox‘a giriş yaparken klavye’de arama butonu gözüküyor olacak;

Sayfaya ApplicationBar, içerisine de ApplicationBarIconButton ekliyoruz, icon olarak feature.search.png dosyasını kullanacağız.

SDK ile birlikte bilgisayarınıza yüklenen örnek icon‘lara aşağıdaki yol ile ulaşabilirsiniz;

C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons

Arama kutusuna kelime girerken arama butonuna basıldığında veya ApplicationBar‘daki arama butonuna basınca Bing üzerinde arama yapacağız, TextBox‘ın KeyUp event’ini ve ApplicationBarIconButton‘ın Click event’ini yakalıyoruz;

private void SearchKey_OnKeyUp(object sender, KeyEventArgs e)
{
	if (e.Key == Key.Enter)
	{
		SearchBing();
	}
}

private void SearchButton_OnClick(object sender, EventArgs e)
{
	SearchBing();
}

Asıl arama olayının döneceği SearchBing() method’unu yazmadan önce projemizde yapmamız gereken düzenlemeler var.

Projenin References‘ına sağ tuşla tıklayıp Nuget Package Manager penceresini açalım ve Microsoft.Data.Services.Client paketini aratalım, OData Client for Windows Phone Apps paketini projeye ekleyelim;

Bing Search API – Web Results Only sayfasından bulabileceğiniz .NET C# Class Library class dosyasını indirip projeye ekliyoruz.

Gelelim SearchBing() method’una;

private void SearchBing()
{
	SystemTray.SetProgressIndicator(this, new ProgressIndicator
	{
		IsVisible = true,
		IsIndeterminate = true,
		Text = "Bing üzerinden arama yapılıyor..."
	});

	var searchUri = new Uri("https://user:[AccountKey]@api.datamarket.azure.com/bing/search");

	var container = new BingSearchContainer(searchUri);
	var query = container.Web(SearchKey.Text, null, null, null, null, null, null, null);

	query.BeginExecute(ar =>
	{
		var state = ar.AsyncState as DataServiceQuery<WebResult>;

		if (state != null)
		{
			var result = state.EndExecute(ar);

			if (result != null)
			{
				Dispatcher.BeginInvoke(() =>
				{
					SearchResultList.ItemsSource = result.ToList();

					SystemTray.SetProgressIndicator(this, null);
				});
			}
		}
	}, query);
}

İlk olarak SystemTray sınıfının static SetProgressIndicator method’unu çağırıyoruz, böylece arama başladığında ekranın üstünde ilerleme çubuğu belirecek;

Bing Search API – Web Results Only sayfasından elde edeceğiniz AccountKey ile Bing Search Uri oluşturuyoruz.

BingSearchContainer sınıfından yeni bir instance oluşturup, Web() method’unu çağırıyoruz, parametre olarak arama kelimemizi veriyoruz.

BeginExecute() method’u ile aramayı başlatıyoruz, gerekli kontrolleri yaptıktan sonra arama sonuç listesini Dispatcher.BeginInvoke içerisinde ekrandaki LongListSelector nesnesine bağlıyoruz.

Son olarak, LongListSelector içerisinde listelenen öğelerden birine tıklandığında ilgili adrese gitmesi için SelectionChanged event’ini yakalıyoruz;

var item = SearchResultList.SelectedItem as WebResult;

if (item != null)
{
	var webBrowserTask = new WebBrowserTask { Uri = new Uri(item.Url, UriKind.Absolute) };
	webBrowserTask.Show();
}

Windows Phone uygulamalarında EnableFrameRateCounter özelliği

26 April 2013 Yorum yapılmamış

Windows Phone uygulamaları geliştirirken elimizin altında basit ama önemli performans ipuçlarının olması işimize yarar.

EnableFrameRateCounter özelliğini açmak

  • Render Thread FPS
  • User Interface Thread FPS
  • Texture Memory Usage
  • Surface Counter
  • Intermediate Texture Counter
  • Screen Fill Rate

değerlerinin ekranda gözükmesini sağlar;

Bu değerler şu anlamlara gelir;

Render Thread FPS
Ekran’ın güncellenme sıklığı. 60 fps civarı güncelleme hızı son kullanıcıya iyi bir deneyim sunacaktır, 30 fps ve üzeri ise kabul edilebilir bir deneyim sunacaktır. Ekran güncelleme hızı 30 fps altınaa düştüğünde bu değer kırmızı olacaktır, dikkat etmek lazım!

User Interface Thread FPS
O esnada çalışan UI thread’in güncellenme sıklığı. Data Binding, animasyonlar ve property change notifications bu thread’de işletilirler. Eğer 15 fps altına düşerse bu değer kırmızı olacaktır, dikkat etmek lazım!

Texture Memory Usage
Çalışan uygulamada kullanılan Texture’ların kullandığı grafik hafıza miktarı

Surface Counter
Graphical Processing Unit (GPU) tarafından işlenecek yüzey miktarı

Intermediate Surface Counter
Önbelleklenmiş bellekler dahil işlenecek yüzey miktarı

Screen Fill Rate
Ekranda güncellenecek piksel miktarı. 1 değeri ekran çözünürlüğü kadar anlamına geliyor, örneğin 480×800. Eğer 1’in altına düşerse veya 2’nin üzerine çıkarsa kırmızı olur, dikkat etmek lazım!

App.xaml.cs dosyasında yeralan

Application.Current.Host.Settings.EnableFrameRateCounter = true;

satırı ile performans ipuçlarını ekranda göstermeye başlayabiliriz.

Uygulamanın son halini MarketPlace‘e göndermeden önce performans ipuçlarının ekranda gözükmediğinden emin olmamız gerekiyor.

Yukarıda ekranın bir parçasının gözüktüğü örnek uygulama için MainPage.xaml dosyasını aşağıdaki şekilde güncellemek gerekiyor;

<phone:PhoneApplicationPage
	x:Class="EnableFrameRateCounterTest.MainPage"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
	xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	mc:Ignorable="d"
	FontFamily="{StaticResource PhoneFontFamilyNormal}"
	FontSize="{StaticResource PhoneFontSizeNormal}"
	Foreground="{StaticResource PhoneForegroundBrush}"
	SupportedOrientations="Portrait" Orientation="Portrait"
	shell:SystemTray.IsVisible="True">

	<phone:LongListSelector Name="lstMessages" />

</phone:PhoneApplicationPage>

MainPage.xaml.cs dosyasında aşağıdaki değişiklikler yapılmalı;

public MainPage()
{
	InitializeComponent();

	var messageList = new List<string>();

	for (int iLoop = 0; iLoop < 150; iLoop++)
	{
		messageList.Add("Long message line #" + iLoop);
	}

	lstMessages.ItemsSource = messageList;
}

Windows Phone 8 LongListSelector DataBind örneği

01 March 2013 3 yorum

Windows Phone 8 uygulamanıza LongListSelector kontrolü eklemeniz ve bir veri kaynağına bağlamanız gerekiyorsa aşağıdaki adımları izleyebilirsiniz.

Öncelikle DataBindSample isimli yeni bir Windows Phone App projesi oluşturalım;

Data Bind Sample Windows Phone Application Project

Proje oluşturduktan sonra gelen Windows Phone Platform versiyon seçim penceresinde Windows Phone OS 8.0 seçeneğinin seçili olduğundan emin olmalıyız;

Windows Phone 8.0 SDK

Bu örnek için Book ve BookList isminde birer class oluşturacağız.

Book sınıfına Title ve Writer isminde iki property ekleyelim;

public class Book
{
	public string Title { get; set; }

	public string Writer { get; set; }
}

BookList sınıfını List<Book> sınıfından türeteceğiz;

public class BookList : List<Book>
{
	public BookList()
	{
		Add(new Book() { Title = "Jurassic Park", Writer = "Michael Crichton" });
		Add(new Book() { Title = "Bourne Identity", Writer = "Robert Ludlum" });
		Add(new Book() { Title = "Devil Wears Prada", Writer = "Lauren Weisberger" });
		Add(new Book() { Title = "Fight Club", Writer = "Chuck Palahniuk" });
		Add(new Book() { Title = "Forrest Gump", Writer = "Winston Groom" });
		Add(new Book() { Title = "Green Mile", Writer = "Stephen King" });
		Add(new Book() { Title = "I Am Legend", Writer = "Richard Matheson" });
		Add(new Book() { Title = "Jaws", Writer = "Peter Benchley" });
		Add(new Book() { Title = "Notebook", Writer = "Nicholas Sparks" });
		Add(new Book() { Title = "Silence of the Lambs", Writer = "Thomas Harris" });
		Add(new Book() { Title = "Spartacus", Writer = "Howard Fast" });
	}
}

BookList sınıfının constructor‘ında listeye birkaç kitap ekliyoruz, böylece uygulamayı çalıştırdığımızda ekrana gelecek liste dolu olacak.

Not : Test süreci sonunda constructor’daki kodlar temizlenmeli ve verikaynağı olarak veritabanına veya bir web service’e bağlanmalıdır.

MainPage.xaml dosyasını aşağıdaki şekilde güncelleyerek ekrana list isminde bir LongListSelector ve DataTemplate özelliğine StackPanel içerisinde TextBlock‘lar ekleyelim;

<Grid x:Name="LayoutRoot" Background="Transparent">
	<Grid.RowDefinitions>
		<RowDefinition Height="Auto"/>
		<RowDefinition Height="*"/>
	</Grid.RowDefinitions>

	<TextBlock Text="databind örnek" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />

	<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
		<phone:LongListSelector Name="list">
			<phone:LongListSelector.ItemTemplate>
				<DataTemplate>
					<StackPanel Orientation="Horizontal">
						<TextBlock Text="{Binding Path=Title}" />
						<TextBlock Text=" ( " />
						<TextBlock Text="{Binding Path=Writer}" FontStyle="Italic" />
						<TextBlock Text=" )" />
					</StackPanel>
				</DataTemplate>
			</phone:LongListSelector.ItemTemplate>
		</phone:LongListSelector>
	</Grid>
</Grid>

Son olarak MainPage.xaml.cs constructor‘ında LongListSelector‘un ItemSource özelliğine BookList sınıfından yeni bir instance atıyoruz;

list.ItemsSource = new BookList();

Artık uygulamayı çalıştırabiliriz, aşağıdaki çıktıyı görüyor olmamız lazım;

Data Bind Sample screen shot

Windows Phone 8 için Radyo Frekansları uygulaması

19 December 2012 Yorum yapılmamış

Windows Phone 8 için şehir-şehir radyo frekanslarını görebileceğimiz bir uygulama geliştireceğiz.

Bu uygulamanın geliştirilmesi sırasında Pivot, PivotItem, LongListSelector, DataTemplate, WebClient gibi sınıfları kullandığımız kodlar yazacağız.

Öncelikle RadyoListe isimli yeni bir Windows Phone App projesi oluşturalım;

Windows Phone App Project

Proje oluşturduktan sonra gelen Windows Phone Platform versiyon seçim penceresinde Windows Phone OS 8.0 seçeneğinin seçili olduğundan emin olmalıyız;

Windows Phone 8.0 SDK

Uygulama ihtiyaç duyduğu veriyi internetten indireceği için WMAppManifest.xml dosyasında Network erişim izninin istenmiş olması gerekiyor;

<Capabilities>
	<Capability Name="ID_CAP_NETWORKING" />
</Capabilities>

Radyo listesi için json formatında hazırladığım veriyi kendi sunucuma radyolar.json ismi ile yükledim.

Json formatında okuyacağımız bu veriyi işlemek için References içerisine Newtonsoft Json.Net (4.5.11) Nuget paketini eklemeliyiz;

Newtonsoft Json.Net Nuget Package

Models isminde bir dizin ekleyip, içerisinde LiveData, City, Channel, Frequency isimli sınıflar oluşturalım;

LiveData.cs

public class LiveData
{
	public IEnumerable<City> Cities { get; private set; }

	public IEnumerable<Channel> Channels { get; private set; }

	public IEnumerable<Frequency> Frequencies { get; private set; }

	public LiveData()
	{
		this.Cities = new List<City>();
		this.Channels = new List<Channel>();
		this.Frequencies = new List<Frequency>();
	}

	public LiveData(string LiveDataResponse)
	{
		var LiveDataResult = JsonConvert.DeserializeObject<LiveData>(LiveDataResponse);

		this.Cities = LiveDataResult.Cities;
		this.Channels = LiveDataResult.Channels;
		this.Frequencies = LiveDataResult.Frequencies;
	}
}

City.cs

public class City
{
	public int ID { get; set; }

	public string Name { get; set; }
}

Channel.cs

public class Channel
{
	public int ID { get; set; }

	public string Name { get; set; }
}

Frequency.cs

public class Frequency
{
	public int CityID { get; set; }

	public int ChannelID { get; set; }

	public float No { get; set; }
}

Uygulama ilk açıldığında çalıştırılan App (App.xaml.cs) sınıfına aşağıdaki kodları ekleyelim;

public static Action DataLoaded;

public static LiveData ViewModel = null;

public async static void LoadData()
{
	WebClient wc = new WebClient();

	wc.DownloadStringCompleted += (s, e) =>
	{
		if (e.Error == null)
		{
			ViewModel = new LiveData(e.Result);

			if (DataLoaded != null)
			{
				DataLoaded();
			}
		}
	};

	wc.DownloadStringAsync(new Uri("http://www.enginpolat.com/application-data/radyolar.json"));
}

App sınıfının constructor’ında LoadData() method’unu çağıralım;

LoadData();

Kodları inceleyecek olursak;

Sınıf seviyesinde tanımlanan LiveData tipindeki ViewModel değişkeni, LoadData() method’u içerisinde asenkron olarak doldurulur. ViewModel değişkenine değer ataması yapıldıktan sonra DataLoaded action‘ını dinleyen bir method varsa tetiklenir.

Bu sayede uygulamanın açılışı esnasında internetten verinin indirilmesi ve deserialize edilmesi asenkron olarak yapılmış olur.

MainPage.xaml dosyasında ekranda sadece bir Pivot kontrolünün gösterilmesini sağlayalım;

<Grid x:Name="LayoutRoot" Background="Transparent">
	<Grid.RowDefinitions>
		<RowDefinition Height="*"/>
	</Grid.RowDefinitions>
	<phone:Pivot Margin="0,10,10,10" Title="Radyo Listesi" Name="pvtSehirListesi" Grid.RowSpan="1" />
</Grid>

Artık MainPage.xaml.cs dosyasındaki constructor‘a giderek ekranı dolduracak kodları yazabiliriz;

App.DataLoaded = () =>
{
	foreach (City Sehir in App.ViewModel.Cities)
	{
		PivotItem pi = new PivotItem();
		pi.Header = Sehir.Name;

		LongListSelector list = new LongListSelector();
		list.ItemTemplate = Application.Current.Resources["FrequencyListItemTemplate"] as DataTemplate;
		list.ItemsSource = (from Frekans in App.ViewModel.Frequencies
			join Kanal in App.ViewModel.Channels on Frekans.ChannelID equals Kanal.ID
			where Frekans.CityID == Sehir.ID
			select new { ChannelName = Kanal.Name, Frequency = Frekans.No.ToString("00.0") }).ToList();

		pi.Content = list;

		pvtSehirListesi.Items.Add(pi);
	}
};

Böylece App sınıfında, ViewModel değişkenine değer yükledikten sonra tetiklediğimiz Action içerisinde bir foreach döngüsü çağırmış oluyoruz.

Döngü içerisinde ilk önce yeni bir PivotItem tipinde değişken oluşturuyoruz ve Header özelliğine döngü değişkeninden elde ettiğimiz şehir ismi bilgisini atıyoruz.

PivotItem tipindeki değişkenin Content özelliğine, LongListSelector tipinde yeni bir değişken atıyoruz.

LongListSelector tipindeki değişkenin ItemsSource özelliğine App.ViewModel değişkenindeki değerlerden LINQ Expression ile oluşturduğumuz listeyi atıyoruz.

Aynı şekilde LongListSelector tipindeki değişkenin ItemTemplate özelliğine

Application.Current.Resources["FrequencyListItemTemplate"] as DataTemplate;

değerini atıyoruz.

Son olarak, App.xaml dosyasına FrequencyListItemTemplate ismindeki Resource‘u ekliyoruz;

<Application.Resources>
	<DataTemplate x:Name="FrequencyListItemTemplate">
		<StackPanel Margin="0,0,0,17">
			<TextBlock Text="{Binding ChannelName}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
			<TextBlock Text="{Binding Frequency}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
		</StackPanel>
	</DataTemplate>
</Application.Resources>

Uygulamayı çalıştırdığımızda aşağıdaki ekran görüntüsünü görüyor olmamız lazım;

Radyo Liste Windows Phone 8 Application

Projenin kodlarını buradan indirebilirsiniz.