Makale Özeti

Bu makalemizde şu ana kadar incelemiş olduğumuz Windows Phone konularından, biraz daha başlangıç seviyesi konulara geri dönerek atlamış olduğumuz ve oldukça önemli olan sayfa oryantasyonu ve sayfa navigasyonu konularını inceleyeceğiz.

Makale

Merhaba, bu makalemizde şu ana kadar incelemiş olduğumuz windows phone konularından, biraz daha başlangıç seviyesi konulara geri dönerek atlamış olduğumuz ve oldukça önemli olan sayfa oryantasyonu ve sayfa navigasyonu konularını  incelemeye çalışacağız. Mobil cihaz ekranlarının doğası gereği küçük olması zaman içerisinde bu cihazların tercih edilmesinin önüne geçmemiş, tam tersine oryantasyon düzeyleri ve hareket kabiliyetleri zaman içerisinde daha da geliştirilerek çok daha fazla tercih edilir noktalara taşınmaya başlamıştır. Özellikle bu gelişimi Windows Phone 7 ile çok daha net hissetmeye başlayacağız.

Windows Phone 7 için geliştirilmiş veya geliştirilmesi planlanan uygulmaları düşünecek olursak tabiiki daha çok bilgilerin listelenmesi gibi bir işleve sahip olan, portrait (düşey) ekran kullanılmaktadır. Fakat yatay düzlemde çok daha iyi görüntülenecek bir veri için telefonumuzu landscape-left (yatayda-sola) veya landscape-right (yatayda-sağa) taraflarına doğru çevirmemiz uygulama içerisinde de dinamik bir şekilde değişim gösterecektir. Aşağıdaki resimlerde Portrait, Landscape-Left, Landscape-Right sayfa oryantasyonlarını görmekteyiz. (Emulatör ile portrait-down elde edilememektedir.)

Windows Phone 7 için bir uygulama geliştirirken, kullanıcının uygulamamızdaki sayfayı hangi oryantasyton ile kullanacağını bilmek bizim için oldukça önemli olacaktır. Bir PhoneApplicationPage sınıfının Orientation özelliğini kullanarak sayfamızdaki oryantasyonu yakalamamız mümkün. Aşağıdaki kod satırlarını kullanarak phone uygulamamızdan oryantasyon değişimlerini kolaylıkla elde edebiliriz.

(İlk uygulamamızı geliştirmeye başlarken Visual Studio 2010 / File / New / Project / Silverlight For Windows Phone / Windows Phone Application Template ile projemizi ekleyebiliriz.)

Constractor içerisinde sayfamızın SupportedOrientations özelliğini set edip, OrientationChanged event'ı ekliyoruz. "oryantasyon" isimli değişkenimizi switch kod snippet kullanarak oluşturduğumuzda aşağıdaki gibi enumarasyon değerlerinin case seçeneklerini oluşturduğunu göreceğiz.

C#

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
        this.SupportedOrientations = SupportedPageOrientation.Portrait |
                                     SupportedPageOrientation.Landscape;
        this.OrientationChanged += MainPage_OrientationChanged;
    }
 
    void MainPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
    {
        var oryantasyon = this.Orientation;
        switch (oryantasyon)
        {
            case PageOrientation.Landscape:
            case PageOrientation.LandscapeLeft:
            case PageOrientation.LandscapeRight:
                MessageBox.Show("Landscape Orientation");
                break;
            case PageOrientation.None:
                break;
            case PageOrientation.Portrait:
            case PageOrientation.PortraitDown:
            case PageOrientation.PortraitUp:
                MessageBox.Show("Portrait Orientation");
                break;
        }
    }
}

Eğer sayfamızda sabit bir oryantasyon kullanılmasının daha uygun olacağını düşünüyorsak, aşağıdaki gibi sayfamızın SupportedOrientations özelliğini xaml kodlarıyla da set etmemiz yeterli olacaktır ve SupportedOrientations özelliğini oryantasyon desteğinin olmasını istediğimiz her sayfa için belirlememiz gerekiyor.

Sayfamıza farklı oryantasyon destekleri verdikten sonra, sayfa üzerinde yer alacak nesnelerin de bu değişimlere göre konumlanması isteyeceğiz. Aksi durumda nesnelerimizin sayfanın dışına taşması, kullanıcının nesneyi görememesi gibi durumlarla karşılaşabiliriz. Aşağıdaki örneğimizde Layout kullanarak butonları yerleştireceğiz. 5 adet farklı button nesnemizin her birini ekranımızın farklı yerine koyarak Horizontal ve Vertical Layout özelliklerini belirleyelim.

XAML

<phone:PhoneApplicationPage 
...
SupportedOrientations="PortraitOrLandscape">
 
 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
     <Button Name="btn1"
             Content="Sol Üst" 
             Height="72" Width="170" 
             HorizontalAlignment="Left"  
             VerticalAlignment="Top" 
             Margin="5" />
     <Button Name="btn2"
             Content="Sağ Üst" 
             Height="72" Width="170" 
             HorizontalAlignment="Right"  
             VerticalAlignment="Top" 
             Margin="5" />
     <Button Name="btn3"
             Content="Sol Alt" 
             Height="72" Width="170" 
             HorizontalAlignment="Left"  
             VerticalAlignment="Bottom" 
             Margin="5" />
     <Button Name="btn4"
             Content="Sağ Alt" 
             Height="72" Width="170" 
             HorizontalAlignment="Right"  
             VerticalAlignment="Bottom" 
             Margin="5" />
     <Button Name="btn5"
             Content="Merkez" 
             Height="72" Width="170"/>
 </Grid>

F5 ile Emulatör üzerinden uygulamamızı çalıştırdığımızda aşağıdaki ekran görnüntülerini elde edeceğiz. (Oryantasyon değişimi için emulatörün sağ yan kısmında bulunan butonları kullanabiliriz.)

Yukarıdaki buttonlar için düzenlediğimiz yöntem ile oryantasyon değişimine karşı önlem almış olduk, fakat bu seferde üst ve alt button nesnelerinin birbirine yaklaştığını görüyoruz. Böylesi bir sayfa da ihtiyacımızı karşılamayacaksa sayfa için ScrollViewer tekniğini kullanabiliriz. ScrollViewer nesnesinin içerisine ContentPanel isimli grid nesnemizi yerleştirelim. Bu yerleşim planının önemli bir noktası grid nesnesine vereceğimiz Height="800" özelliği olacak. ScrollViewer da kullanarak XAML kodlarımızı aşağıdaki gibi hazırlayalım.

XAML

<Grid x:Name="LayoutRoot" Background="Transparent">
   <ScrollViewer HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch"
                 VerticalScrollBarVisibility="Auto" >
       <Grid x:Name="ContentPanel" Height="800">
           <Button Name="btn1"
               Content="Sol Üst" 
               Height="72" Width="170" 
               HorizontalAlignment="Left"  
               VerticalAlignment="Top" 
               Margin="5" />
           <Button Name="btn2"
               Content="Sağ Üst" 
               Height="72" Width="170" 
               HorizontalAlignment="Right"  
               VerticalAlignment="Top" 
               Margin="5" />
           <Button Name="btn3"
               Content="Sol Alt" 
               Height="72" Width="170" 
               HorizontalAlignment="Left"  
               VerticalAlignment="Bottom" 
               Margin="5" />
           <Button Name="btn4"
               Content="Sağ Alt" 
               Height="72" Width="170" 
               HorizontalAlignment="Right"  
               VerticalAlignment="Bottom" 
               Margin="5" />
           <Button Name="btn5"
               Content="Merkez" 
               Height="72" Width="170"/>
       </Grid>
   </ScrollViewer>
</Grid>

XAML kodlarımızda yaptığımız düzenlemeden sonra tekrar F5 ile uygulamamızı çalıştırdığımızda aşağıdaki ekran görüntüleri ile karşılaşacağız. Dikkat edecek olursak ScrollViewer nesnemizin VerticalScrollBarVisibility özelliğini Auto olarak ayarlıyoruz. Bu kullanım yöntemi ile de oryantasyon değişiminde dikey düzlemde sayfa üzerinde parmakla kaydırarak kullanarak, ekran üzerindeki nesnelerimi kaybetmeden ve sıkışık bir görüntü oluşturmadan kullanabiliriz.

ContentPanel isimli Grid nesnesinin Height özelliği 800 olarak belirlendiği için Landscape konumdayken sayfa üzerinde aşağıya ve yukarıya doğru gezinebilme olanağı yakalamış oluyoruz.

Sayfa oryantasyonları ile ilgili önemli noktaları belirledikten sonra, şimdi de sayfalar arasındaki geçişleri incelemeye başlayalım;

Sayfa Navigasyonu

Şimdiye kadar örneklerimizi tek bir sayfa üzerinden gerçekleştirdik. Uygulamamız içerisinde tabiki bir den fazla sayfaya ihtiyaç duyabiliriz. Daha önceki bir makalemizde de Panorama ve Pivot Control' e değinmiştik (Windows Phone'da Panorama ve Pivot Control :  http://www.yazgelistir.com/Makaleler/1000002595.ygpx) Panorama veya Pivot control kullanımı ile hızlı görüntü geçişleri elde etmiştik. Farklı sayfalara da kolaylıkla erişebiliriz.

Yukarıdaki, köşelere eklediğimiz buton nesneli örneğimizi silmeden projemize SecondPage.xaml isimli bir sayfa daha ekleyelim. Bu butonların Click event'ı üzerinden farklı navigasyon yöntemleriyle ikinci sayfayı görüntülemeye çalışacağız.

C# (MainPage)

private void btn1_Click(object sender, RoutedEventArgs e){
    var frame = Application.Current.RootVisual as PhoneApplicationFrame;
    frame.Source = new Uri("/SecondPage.xaml",UriKind.Relative);
}
 
private void btn2_Click(object sender, RoutedEventArgs e){
   var frame = Application.Current.RootVisual as PhoneApplicationFrame;
   frame.Navigate(new Uri("/SecondPage.xaml"UriKind.Relative));
}
 
private void btn3_Click(object sender, RoutedEventArgs e){
   this.NavigationService.Navigate(new Uri("/SecondPage.xaml"UriKind.Relative));
}

Peki bu ana sayfadan ayrılmadan önce kullanıcının eksik bırakmış olduğu bir takım verilerin olduğunu varsayarsak, bu durumda kullanıcıdan onay alarak diğer sayfaya geçiş yapabiliriz.

C# (MainPage)

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
    if (MessageBox.Show("Sayfadan ayrılmak istiyor musunuz?""Onay", 
        MessageBoxButton.OKCancel) != MessageBoxResult.OK)
    {
        e.Cancel = true;
    }
    base.OnNavigatingFrom(e);
}

Eğer sayfalar arasındaki navigasyon geçişlerini izlemek isterseniz, App sınıfı constractor içerisine aşağıdaki kod satırlarını ekleyerek debug da iken bunu da sağlayabilirsiniz.

C# (App)

public App()
{
    UnhandledException += Application_UnhandledException;
    if (System.Diagnostics.Debugger.IsAttached)
    {
        Application.Current.Host.Settings.EnableFrameRateCounter = true;
    }
    InitializeComponent();
    InitializePhoneApplication();
 
    RootFrame.Navigating += App_Navigating;
}
 
void App_Navigating(object sender, NavigatingCancelEventArgs e){
    Debug.WriteLine("Navigating to " + e.Uri);
}

Sayfalar arasında veri transfer edebilmek için de 2 farklı yöntemi ele alacağız. Bunlardan ilki FragmentNavigation.  Bir sayfadan diğerini navigate ederken # işareti ile aşağıdaki kod satırlarında olduğu gibi veriyi de eklemek. btn1 isimli buton nesnemizin Click event'ını değiştirerek aşağıdaki gibi yazalım. MainPage'den SecondPage'e  "Merhaba Dünya :)" verisini gönderelim.

C# (MainPage)

private void btn1_Click(object sender, RoutedEventArgs e){
    this.NavigationService.Navigate(new Uri("/SecondPage.xaml#Merhaba Dünya :)",
                                    UriKind.Relative));
}

C# (SeconPage)

public partial class SecondPage : PhoneApplicationPage
{
    public SecondPage()
    {
        InitializeComponent();
    }
 
    protected override void OnFragmentNavigation(FragmentNavigationEventArgs e)
    {
        base.OnFragmentNavigation(e);
        MessageBox.Show("Fragment : " + e.Fragment);
    }
}

F5 ile uygulamamızı başlatalım. Bir taraftan Output penceresinden de navigate ettiğimiz bilgileri de göreceğiz.

Sayfalar arasın veri transferindeki ikinci yöntemimiz ise QueryString yöntemi. Bu yöntemde de navigate ettiğimiz sayfanın sonuna ? ekleyerek değerlerimizi & işaretcisi ile ayırarak yazmak. Aşağıdaki örnekte MainPage'den SecondPage sayfasına MusteriID ve UrunKodu değerlerini göndereceğiz.

C# (MainPage)

private void btn1_Click(object sender, RoutedEventArgs e){
    this.NavigationService.Navigate(
        new Uri("/SecondPage.xaml?MusteriID=15 & UrunKodu=77",UriKind.Relative));
}

C# (SecondPage)

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    StringBuilder sb = new StringBuilder();
    foreach (var item in NavigationContext.QueryString)
    {
        sb.AppendLine("Query String Key: " + item.Key + "  Value: " + item.Value);
    }
    MessageBox.Show(sb.ToString());
}

Tekrar F5 ile emulatör üzerinden sayfa navigasyonumuzu QueryString olarak NavigationContent nesnesi içerisinden çekerek makalemizi sonlandıralım.

Bu makalemizde sayfa yapıları, sayfalar arası geçişler/navigasyon konularına değindik. Dilerim faydalı bir yazı olmuştur.

Bir sonraki makalemizde görüşmek üzere...

Kolay gelsin.

Gökhan Manduz
gokhanmanduz.blogspot.com