15 Temmuz 2011 Cuma

Sharepoint 2010: The deployment type "TemplateFile" of file in Project Item is not compatible with a Feature in a Sandboxed Solution

Sharepoint 2010'da uygulama geliştirken wsp paketi oluşturma sırasında aşağıdaki hataları alırsanız;

The deployment type "TemplateFile" of file "%ascxName%" in Project Item "%VisualWebPartName%" is not compatible with a Feature in a Sandboxed Solution.

The Project Item "%VisualWebPartName%" cannot be deployed through a Feature in a Sandboxed Solution.

Sharepoint projenize eklediğiniz Visual Web Part'la ilgili bir ayar sorunu olduğu anlamına geliyor. Bu durumda kontrol etmeniz gereken 2 şey var.

  1. Sharepoint projenize eklediğiniz Visual Web Part'ızın ascx elemanına sağ tıklayıp Properties ekranına geçiyoruz.
























    Açılan Properties ekranında Deployment Type olarak Template File seçiyoruz.
























  2. Yukarıdaki ayar zaten Template File olarak seçiliyse, Sharepoint solution tipiniz zamanında Sandboxed olarak (varsayılan budur zaten) seçilmiştir ve Sandboxed projeler Visual Web Part elemanını içerdiğinde paketlemede bu hatayı alırsınız. Düzeltmek için, Solution Explorer penceresinde iken Sharepoint projemizi seçiyoruz ve Properties penceresine geçiyoruz.























    Properties penceresinde Sandboxed Solution değerini False olarak değiştiriyoruz ve kaydediyoruz.





















Bu değişiklikleri yaptıktan sonra projemiz bundan sonra Farm solution olarak sunulacak ve Visual Web Part'ları destekler hale gelecektir. Paket almaya çalıştığımızda da sorunsuz bir şekilde wsp paketinin oluşturulduğunu göreceğiz.

Kolay gelsin,

Wsp paketi Sharepoint'e nasıl deploy edilir?

Birçok bileşen içeren Sharepoint uygulamanızı geliştirdiniz. Yeri geldi class library'ler, yeri geldi Silverlight uygulamaları olan tüm bu bileşenlerinizi daha önceki postlarda anlattığım şekilde Sharepoint paketinize eklediniz ve paketinizi oluşturup elinizde bir wsp dosyası ile hazır bekliyorsunuz :)

Şimdi bu wsp'yi ne yapıcaz da Sharepoint sunucumuza deploy edicez? Şimdi öncelikle bu deployment süreci elinizdeki Sharepoint projesinin tipine göre değişiklik gösteriyoruz. Proje ilk yaratılırken bir ekranda sormuştu hatırlıyor musunuz projeyi hangi tip istersin diye?


















Hatırlarsın hatırlarsın. Hatta bunu "amann default'u neyse o olsun" diye sandbox'ta bırakıp daha sonra bu posttaki hatayı aldıktan sonra farm'a çevirmiş olabilirsin ;)

Neyse, adım adım Farm ve Sandboxed solution'a göre wsp kurulumu şu şekilde;

Farm
  1. Kurulum yapacağımız Sharepoint sunucusunda güzel bir yere wsp dosyamızı yerleştiriyoruz. Daha sonra Sharepoint 2010 Management Shell komut satırını açıyoruz.

  2. Öncelikle solution'ı ekleme işlemini yapıyoruz. Şöyle:
    Add-SPSolution –LiteralPath "C:\wspName.wsp"
    Bu işlemden sonra bize hangi solutionId ile kaydedildiğini gösteriyoruz. Dikkat ederseniz henüz deploy edilmediğini göreceksiniz.




  3. Daha sonra wsp dosyamızı Install komutu ile Sharepoint sunucumuza yüklüyoruz.
    Install-SPSolution –Identity wspName.wsp –WebApplication http://portalAddress –GACDeployment

  4. Yükleme sonrasında portalımızı açıyoruz. Kökteki sitemiz üzerinden Site Settings --> Site Collection Features ekranına gidiyoruz ve kurulum sonrası burada görünür hale gelen feature'ımızı aktif hale getiriyoruz.




Sandboxed
  1. Kurulum yapacağımız Sharepoint sunucusunda güzel bir yere wsp dosyamızı yerleştiriyoruz. Daha sonra Sharepoint 2010 Management Shell komut satırını açıyoruz.

  2. Öncelikle solution'ı ekleme işlemini yapıyoruz. Şöyle:
    Add-SPUserSolution –LiteralPath "C:\wspName.wsp" –Site http://webapplication/sitecollection

  3. Daha sonra wsp dosyamızı Install komutu ile Sharepoint sunucumuza yüklüyoruz.
    Install-SPUserSolution –Identity SPTestProject.wsp –Site http://webapplication/sitecollection

  4. Yükleme sonrasında portalımızı açıyoruz. Kökteki sitemiz üzerinden Site Settings --> Site Collection Features ekranına gidiyoruz ve kurulum sonrası burada görünür hale gelen feature'ımızı aktif hale getiriyoruz.



Sadece ilk defaya mahsus olmak üzere yükleme işlemini bu şekilde yaptık. Peki daha sonrası? Yeniden oluşturduğumu wsp paketini yine sunucuda uygun bir yere atıyoruz. Sharepoint 2010 Management Shell komut satırımızı açıyoruz ve şu komutu yürütüyoruz;

Farm

Update-SPSolution –Identity wspName.wsp –LiteralPath “C:\wspName.wsp” –GacDeployment


Sandboxed

Update-SPUserSolution –Identity wspName.wsp –Site http://webapplication/site –ToSolution wspName.wsp


Artık bu wsp paketini kullanmak istemiyorsak da sırasıyla;

Farm
  1. Paketi uninstall ediyoruz.
    Uninstall-SPSolution –Identity wspName.wsp –WebApplication http://webapplication

  2. Paketi kaldırıyoruz.
    Remove-SPSolution –Identity wspName.wsp

Sandboxed

  1. Paketi uninstall ediyoruz.
    Uninstall-SPUserSolution –Identity wspName.wsp –Site http://webapplication/sitecollection

  2. Paketi kaldırıyoruz.
    Remove-SPUserSolution –Identity wspName.wsp –Site http://webapplication/sitecollection


Bu şekilde wsp paketlerini Sharepoint portalına yükleme, güncelleme ve çıkarma işlemlerini görmüş olduk. Acılı süreçler gibi görünse de el alışkanlığı ve komut satırının yetenekleri sayesinde zamanla alışılıyor :)

Kolay gelsin,

Sharepoint 2010: File Not Found

Sharepoint 2010 uygulamanızı geliştirdiniz. Sunucuya deploy ettiğiniz. Çalışma sırasında şu hatayı aldınız;














Ne diyor hata? "File Not Found"

Şimdi, bunun birçok nedeni olabilir. Benim rastladıklarımdan birkaçı;
  1. Kod içerisinde sayfa ya da listelere ulaşmaya çalışırken bir isimlendirme hatası yapmış olabilirsiniz.

  2. Client Object Model üzerinden, listelere, internal name yerine listelerin görünen isimleriyle ulaşmaya çalışıyorsanız (ki yanlış bir yaklaşım) ve listenin görünen ismi değişmişse patlarsınız ("Aaa daha sabah çalışıyordu yaa" hadisesi burdan gelir). Unutmayın listelerin görünen isimleri değişebilir ancak internal name'leri ilk yaratılırken verilir ve bir daha değişmez.

  3. Son karşılaştığım durumu da şu postta 2. maddede anlatmıştım. Bu da çok sık karşılaşılan bir durum.

Kolay gelsin,

Sharepoint 2010: Assembly generation failed -- Referenced assembly does not have a strong name

Sharepoint 2010 üzerinden uygulama geliştirirken derleme sırasında şu hatayı alırsanız;

Assembly generation failed -- Referenced assembly '%assembly name%' does not have a strong name

hiç üzülmeye gerek yok. Çözülmüşü var ;)

Sharepoint Projesinde Class Library nasıl kullanılır?

Diyelim ki kapsamlı bir Sharepoint projesi geliştiriyorsunuz. Bu projenizi, katmanlı mimarinin ve yazılım geliştirme mantığının doğası gereği alt projelere böldünüz. Core, Logging, UI vs... Bu durum aslında geliştirdiğimiz her projede rastladığımız bir senaryo. Bu makalede çözmeye çalıştığımız durum da bu senaryonun bir Sharepoint 2010 projemizde başımıza gelmesi durumu. İnceleyelim.

Şimdi diyeceksiniz, "amann ne var canım bunda, class library'i sharepoint projesinde referans olarak göster bitsin gitsin!" Ama öyle olmuyor maalesef, yani olmuyormuş ben de patlayınca öğrendim :) Adım adım Class Library, Sharepoint projesinde nasıl kullanılır görelim:

  1. İlk adım zaten her zaman yaptığımız gibi, Class Library'i geliştirdikten sonra, kullanmak istediğimiz Sharepoint projesinde referans olarak göstermek.
























    Yalnız ne zaman ki bu class library elemanlarını, Sharepoint projesinde kullanıyoruz (ki zaten kullanmak için referans olarak ekledik) build sırasında şu hatayı alırız;

    Assembly generation failed -- Referenced assembly 'CoreLibrary' does not have a strong name

    Eklediğimiz Class Library'i her Sharepoint bileşeni gibi strong name ile işaretlemek gerektiğini söylüyor hata. Bunu da yapmak için, Class Library projemizi sağ tıklayıp Properties ile özelliklerine gidiyoruz. Açılan ekranda sol menüden Signing'i seçtikten sonra sağ menüde Sign the assembly kutucuğunu seçili hale getirip, Choose a strong name key file açılır menüsünde New seçimini yapıyoruz.
















    Yeni açılan ekranda, Key File Name'e istediğimiz bir ismi verdikten sonra, gerek olmadığı için "Protect my key file with a password" seçimini kaldırıyoruz ve Ok'liyouz.















    Bu şekilde class library'imizi strong key name ile işaretledikten sonra projemizi derlediğimizde herhangi bir hata almadığımızı göreceğiz.


  2. Peki bitti mi? Hayır tabii ki! Bu şekilde bırakıp, paketleme işlemi yaparsak paketlenmiş wsp dosyamız içerisinde Class Library dll'imiz olmadığını göreceğiz. Bu durum da deployment sonrasında şu postta yazmış olduğum hatayı beraberinde getirecek. Bu nedenle class library dll'imiz bir şekilde pakete eklememiz gerekiyor.

    Bunun için öncelikle Sharepoint projemiz altındaki Package.package elemanına çift tıklıyoruz.
















    Açılan ekranda bir bakıyoruz ki soldaki sütunda pakete eklenecek elemanlar arasında Class Library'imiz yok! Aaa!











    Nerde bu diye dövünmeye gerek yok. Sol alttaki Advanced butonuna tıklıyoruz. Yeni açılan ekranda Add --> Add Assembly from Project Output işlemini yapıyoruz.




    Yeni açılan ekranda Source Project olarak ilgili Class Library'imizi, Deployment Target olarak da varsayılan olan GlobalAssemblyCache'i seçiyoruz ve Ok'liyoruz.
























    Kaydettikten sonra paketleme işlemi yaptığımızda wsp içerisinde bu sefer Class Library dll'imizin olduğunu görüyoruz. Bu wsp'yi de şu postta anlattığım üzere sunucuya deploy ettikten sonra Class Library'imizi kullanan bir webpart sahibi olduğumuzu görüyoruz.
Görüldüğü üzere Sharepoint 2010 projelerimizde Class Library kullanmak bir miktar çetrefilli. Ancak bu işlemi sadece bir kez yapıyorsunuz ve inanın SP 2007'den sonra bu çetrefil sayılmaz ;)

Kolay gelsin,

Silverlight Web Part nasıl debug edilir?

Her geliştirdiğimiz uygulamada olduğu gibi Sharepoint 2010 üzerinde geliştirdiğimiz Silverlight web part'larda da zaman zaman debugging ihtiyacımız olduğu bir gerçek. Varsayılan olarak bu özellik başta kapalıdır, isteğe bağlı olarak açılabilmektedir. Nasıl yapıldığını görelim;

Solution Explorer'ımızda Sharepoint Projemize (Silverlight projemiz değil!) sağ tıklayıp Properties'i seçiyoruz.
























Açılan proje özellikleri ekranında sol menüden SharePoint tabını seçtikten sonra sağ menüde en altta yer alan Enable Silverlight debugging (instead of Script debugging) alanını seçili hale getiriyoruz ve kaydediyoruz.




















İşte bu kadar. Bu işlemden sonra debug etmeye çalıştığımızda Silverlight web part'ların da içerisindeki kodlarda gezinebileceğiz ;)









Kolay gelsin,

14 Temmuz 2011 Perşembe

Silverlight Web Part Sharepoint'e nasıl deploy edilir?

Daha önce yazdığım postta Silverlight Web Part'ların kendi yarattığımız bir doküman kütüphanesi kullanarak Sharepoint portalı üzerinde nasıl host edileceğini yazmıştım. Ancak bu tip bir yüklemenin bazı sakıncaları var. Öncelikle zaman kaybı. Her build çıktısı olan .xap dosyasını tek tek bu doküman kütüphanesine upload etmek vs. kolay gibi görünen ama zaman ve dikkat gerektiren bir iş. Diğer bir zorluğu ise, eğer kullanılan portalın üzerinde yetkinizin olmadığı kurumsal bir firmada (benim gibi) çalışıyorsanız bu kurulumu sizin için üstlenecek bazı birimlere/kişilere kurulum paketini iletmeniz gerekmesi ve bu pakette mümkün olduğunda az bileşen olmasının, kurulumun başarılı olma olasılığı ile doğrudan orantılı olması ;)

Şimdi bu durum için nasıl bir çözüm bulmuş Sharepoint? Yetkinizin olduğu makinelere kurulum yaparken bir sorun yok zaten, Visual Studio 2010 üzerinde açık bir Sharepoint 2010 projesinden Deploy komutu ile sunucuya direkt olarak deploy işlemini yapabilirsiniz. Ama erişemediğiniz uzak sunucular veya yetkinizin olmadığı sunucular içinse Package mantığını geliştirmişler. Sharepoint projenizdeki tüm bileşenleri paketleyerek wsp uzantılı bir dosya haline getiriyor ve sizin kurulum paketiniz aslında bu tek dosya oluyor. Kurulumu yapacak kişi ise bu tek dosyayı, Sharepoint 2010 Management Shell'de yazacağı tek bir komutla sunucuya deploy ediyor.

Package mantığını uzun uzun anlatmaya gerek yok. Ama birkaç şey bilmekte fayda var. Öncelikle paket nasıl yapılır? Paketleme build'den farklı bir şeydir öncelikle. Build sonrasında wsp uzantılı dosyanız oluşmaz. Paket oluşturmak için solution explorer'dan Sharepoint Projenize sağ tıklayarak "Package" komutunu çalıştırıyoruz.
























Paketleme başarılı olduktan sonra projenin Bin/Debug klasöründe wsp uzantılı dosyanın oluştuğunu göreceğiz.










Şimdi test etmek açısından bu wsp dosyasının uzantısını zip yapıyoruz! Evet bu aslında sıkıştırılmış bir dosya ;) Uzantısını zip'e çevirdikten sonra açıyoruz içini bakıyoruz ne var ne yok.









Gördüğünüz gibi manifest dosyamız ve Sharepoint proje dll'imiz var zip içerisinde. Yani deployment için sadece bu wsp dosyasınız gerekli yerlere iletmemiz yeterli. Şimdi asıl makalemizin konusuna geliyoruz. Benim paketini aldığım solution içerisinde aşağıda gördüğünüz gibi bir de Silverlight Application projesi vardı ancak kendisinin xap uzantılı çıktısı paketimiz içerisinde oluşmadı.

















Normalde paket içeriğini güncellemenin bir yolu var. Sharepoint projesinde Package isimli klasörü açtığınızda içerisindeki Package.package simgesinden Paket içeriğimizi görsel olarak görebileceğimiz arayüze ulaşabiliriz.



















Arayüz ise şu şekilde;











Burada sol taraf solution içerisindeki pakete dahil edilmemiş bileşenleri gösterirken, sağ taraf pakete dahil edilmiş olanları gösteriyor. Ama o da ne?! Silverlight Application pakette çıkmamasına rağmen, sol tarafta da gözükmüyor! Eee nasıl atıcam ben bu arkadaşı pakete?

Module

İşte Sharepoint 2010'un diğer mucizelerinden biri :p Module elemanını kullanarak Silverlight Application'larınızı paket içerisine dahil edebilirsiniz. Şu şekilde;

Öncelikle Sharepoint Projenize sağ tıklayarak Add -> New Item ile yeni eleman ekleme ekranınız açıyoruz. Bu ekranda solda Sharepoint 2010 seçiliyken, sağdaki ekrandan Module seçimini yapıyoruz ve belirlediğimiz bir isimle Modülümüzü projemize ekliyoruz.

















Modulümüzü ekledikten sonra Solution Explorer'dan kendisine sağ tıklayarak Properties menüsünü açıyoruz.




















Properties menüsünde Project Output References satırındaki seçim butonuna basıyoruz.
















Yeni açılan Project Output References ekranında, önce Add işlemi ile yeni bir eleman ekliyoruz. (Bu noktada birden fazla Silverlight uygulamanız varsa onları da ekleyebilirsiniz.) Eklenen yeni elemanın sol menüdeki özelliklerini, Deployment Type -> ElementFile; Project Name ise ilgili Silverlight web application'ımız olacak şekilde güncelledikten sonra Ok'liyoruz.


















Artık Silverlight projemizi de bir modül olarak paket yapısına eklemiş bulunuyoruz. Paketimizi oluşturalım. Bunun için Solution Explorer'dan Sharepoint projemize sağ tıklayarak Package komutunu çalıştıralım. Daha sonra projenin bin/Debug klasörü altında yeni oluşmuş wsp dosyasını bulalım. Kontrol etmek için uzantısını yine zip olarak değiştirelim ve zip klasörünü açalım.









Zip klasörünün içerisinde gördüğünüz gibi bir Feature klasörü var. Bu klasörün içerisine girdiğimizde de Module klasörümüzün içinde Silverlight projemizin çıktısı olan xap uzantılı dosyamızın olduğunu göreceğiz.









Böylece deployment paketimize Silverlight application çıktımız olan xap dosyamızı bir modül olarak eklemiş olduk. Artık sunucumuza deploy işlemi yaptığımızda xap dosyamız da iletilecek. Peki bitti mi? Bitmedi. Neden? Eee sunucuya xap dosyamızı gönderdik. Ama Sharepoint portalımızdaki sayfamıza bu Silverlight Application'ımızı bir web part olarak göstermemiz gerekiyor değil mi. Bu da bir kereye mahsus olmak üzere şöyle yapılıyor. Portal üzerinde yeni bir sayfa açıyoruz. Sayfanın edit modunda üst menüdeki Insert tabından Web Part seçiyoruz.









Web part menüsünde solda Media and Content tipini seçip, daha sonra sağda açılan menüden Silverlight Web Part seçeneğini seçerek Add yapıyoruz.







Açılan pop-up ekrana /Modul ismimiz/xap dosya adımız.xap şeklinde xap dosyamızın adresini giriyoruz. Benim örneğimde bu değer /SLModule/SLWebPart.xap oluyor.











Ok'ledikten sonra xap adresinde bir hata yoksa web part'ımız direkt açılıyor ve kullanıma hazır hale geliyor ;)

Bundan sonra yapılacak deployment işlemlerinde sadece wsp paketini sunucuya kurmak yeterli oluyor, paketle birlikte giden Silverlight uygulamalarını tekrar tekrar kurmaya gerek kalmıyor.

Kolay gelsin,

13 Temmuz 2011 Çarşamba

Silverlight Web Part Tarih Problemi

Şirkette bir süredir çalıştığım Sharepoint 2010 projesinde, Silverlight Web Part'lar kullanmaya karar verdiğimizden beri çeşitli sıkıntılar yaşıyorum ve bunlardan en ilginci de birazdan anlatacağım tarih problemi.

Örnek olarak Sharepoint 2010 üzerindeki Tasks listesini vereceğim. Bu listede yer alan görev elemanlarının Date and Time tipinden bir "Start Date" özelliği mevcut ve görevin başlama tarihini işaret ediyor kendisi. Pekii.. O zaman bu Task listesinin elemanlarını Client Object Model kullanarak Silverlight Web Part'ımızda gösterelim. Öncelikle listemiz:








Bu da yazdığımız ufak uygulamanın ekran çıktısı:












Aaa, o ne yaa? Bu tarihler farklı?! Xaml'deki language ayarını bir Tr-tr yapın bakalım. Oldu mu? Olmadı.. Çekilen datetime değerlerini Türkçe region ayarlarına göre formatlayın, deneyin. Oldu mu? Yine olmadı. Çaresizce Sharepoint portalı, sitesi, kullandığınız istemci bilgisayarın tüm dil ayarlarını Türkçe yapın bakalım. Bu sefer olmuştur ama. Yine mi olmadı? Olmaz abi olmaz. Ben hepsini yaptım olmadı çünkü :)

Sorunun nedeni regional ayarlar ama haklısınız. Hatta dikkat ederseniz listedeki değerler ile Client Object Model'den gelen değerler arasında tam olarak 3 saatlik bir fark olduğunu göreceksiniz. Eee nasıl çözülecek bu? Şimdi nette uzun uğraşlar sonucunda şöyle bir makale buldum ve burada anlatılanların işe yaradığını gördüm. Yalnız burada arkadaş Console Application örneği üzerinden gitmiş ve bu nedenle yapılan çağrıların hepsi senkron. Ancak biz UI içeren Silverlight uygulaması kullandığımız için çağrılarımız asenkrondu hatırlarsanız. Ben de bu makalede asenkron çağrılar kullanarak tarih formatı düzeltme işleminin nasıl yapılacağını anlatacağım.

Yine bir örnek uygulama üzerinden gidelim. Tasks listesindeki Görevleri Silverlight Web Part'ımızda başlangıç tarihleri ile birlikte gösteren bir uygulama geliştirelim. Öncelikle önyüzümüz olan Xaml kodumuza gerekli ekran elemanlarını ekliyoruz.
<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"  x:Class="SLWebPart.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xml:lang="tr-TR"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Vertical">
<Button x:Name="btnGorevGetir" Content="Tüm Görevleri Getir" Click="btnGorevGetir_Click"
Width="200" Height="50"></Button>
<sdk:DataGrid x:Name="taskGrid" AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Görev No" Binding="{Binding GorevID}"/>
<sdk:DataGridTextColumn Header="Görev Rolü" Binding="{Binding GorevAdi}" />
<sdk:DataGridTextColumn Header="Bağlı Talep" Binding="{Binding BaslangicTarihiAfter}" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</StackPanel>
</Grid>
</UserControl>
Görüldüğü gibi önyüzümüzde görevleri çekme komutunu veren bir buton ve görevleri listelediğimiz bir grid olacak.

Asıl iş olan code-behind'da normalden farklı olarak yapmamız gereken işlem şu; Asenkron bir çağrı ile çektiğimiz liste verilerinden tarih olanı formatlayarak tekrar bir asenkron çağrı yapmak. Bunu da tahmin edebileceğiniz üzere OnSuccess callback metodu içerisinde yapacağız. Görelim;
private void success()
{
taskList = new List<Task>();

foreach (ListItem item in taskCollection)
{
Task newTask = new Task();
newTask.GorevID = Convert.ToInt32(item["ID"]);
newTask.GorevAdi = Convert.ToString(item["Title"]);

DateTime baslangicTarihiWrong = Convert.ToDateTime(item["StartDate"]);
newTask.BaslangicTarihiBefore = Utility.FormatDateTime(spContext, spContext.Web, baslangicTarihiWrong, DateTimeFormat.DateTime);

taskList.Add(newTask);
}

spContext.ExecuteQueryAsync(TarihSuccess, OnFailure);
}
Burada can alıcı nokta Utility.FormatDateTime kullanımı. Bu metot ile Client Object Model'den yanlış olarak çekilen tarihi formatlama işlemini gerçekleştiriyoruz. Yalnız formatladıktan sonra işimiz bitiyor mu? Tabii ki hayır! Bu metot bize ClientResult tipinde bir değer dönüyor ve bu değer tahmin edebileceğiniz üzere hemen kullanılamıyor. Ne zaman kullanılabilir? Tabii ki asenkron bir çağrı yapıp ClientContext'e yüklendikten sonra. Eee ben kocaman bir listede her elemanın tarihini formatlamak için asenkron bir çağrı mı yapacağım?! Tabii ki hayır! Bunun için birkaç yöntem kullanılabilir. Benim uydurduklarımdan bir tanesi, list item tipini çevirdiğiniz kendi veri tipiniz içerisinde ClientResult tipinde bir Property yaratmanız ve örnekte de görüldüğü üzere ilk atama işlemini bu property'e yapmanız. Daha sonra yaptığınız asenkron çağrının Success'inde ise bu Property'nin datetime value'sunu okumanız. Görelim;
private void tarihSuccess()
{
foreach (Task item in taskList)
{
item.BaslangicTarihiAfter = Convert.ToDateTime(item.BaslangicTarihiBefore.Value);
}

taskGrid.ItemsSource = taskList;
}
ClientResult nesnesinin Value property'si bize formatlanmış tarih değerini verecektir.

Code behind'ın tümü:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;

namespace SLWebPart
{
public partial class MainPage : UserControl
{
ClientContext spContext;

ListItemCollection taskCollection;
List<Task> taskList;

private delegate void SuccessDelegate();
private delegate void FailDelegate(Exception ex);

public MainPage()
{
InitializeComponent();
}

private void btnGorevGetir_Click(object sender, RoutedEventArgs e)
{
spContext = new ClientContext("http://t1wsportal01/TalepYonetimi/");
List taskList = spContext.Web.Lists.GetByTitle("Tasks");

CamlQuery query = new CamlQuery();
query.ViewXml = String.Format(@"<View><Query></Query></View>");

taskCollection = taskList.GetItems(query);

spContext.Load(taskCollection);
spContext.ExecuteQueryAsync(OnSuccess, OnFailure);
}

private void OnFailure(object sender, ClientRequestFailedEventArgs e)
{
FailDelegate delegateMethod = fail;
this.Dispatcher.BeginInvoke(delegateMethod, e.Exception);
}

private void fail(Exception ex)
{
MessageBox.Show(ex.Message);
}

private void OnSuccess(object sender, ClientRequestSucceededEventArgs e)
{
SuccessDelegate delegateMethod = success;
this.Dispatcher.BeginInvoke(delegateMethod);
}

private void success()
{
taskList = new List<Task>();

foreach (ListItem item in taskCollection)
{
Task newTask = new Task();
newTask.GorevID = Convert.ToInt32(item["ID"]);
newTask.GorevAdi = Convert.ToString(item["Title"]);
DateTime baslangicTarihiWrong = Convert.ToDateTime(item["StartDate"]);
newTask.BaslangicTarihiBefore = Utility.FormatDateTime(spContext, spContext.Web, baslangicTarihiWrong, DateTimeFormat.DateTime);

taskList.Add(newTask);
}

spContext.ExecuteQueryAsync(TarihSuccess, OnFailure);
}

private void TarihSuccess(object sender, ClientRequestSucceededEventArgs e)
{
SuccessDelegate delegateMethod = tarihSuccess;
this.Dispatcher.BeginInvoke(delegateMethod);
}

private void tarihSuccess()
{
foreach (Task item in taskList)
{
item.BaslangicTarihiAfter = Convert.ToDateTime(item.BaslangicTarihiBefore.Value);
}

taskGrid.ItemsSource = taskList;
}
}
}

Task sınıfımız:
using System;
using Microsoft.SharePoint.Client;
namespace SLWebPart
{
public class Task
{
public int GorevID { get; set; }
public string GorevAdi { get; set; }

public ClientResult<string> BaslangicTarihiBefore { get; set; }
public DateTime BaslangicTarihiAfter { get; set; }
}
}
Uygulamamızı portalımıza web part olarak yükledikten sonra çalıştıralım:












Görüldüğü gibi tarihler artık doğru bir şekilde gösteriliyor.

Kolay gelsin,



The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

Sharepoint 2010'da geliştirdiğiniz Silverlight uygulamasından şu hatayı alıyorsanız;

The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

Henüz ClientContext'e Load edilmemiş bir elemanı kullanmaya çalıştığınızı işaret eder. Mesela;
ClientContext spContext = new ClientContext("http://t1wsportal01/TalepYonetimi/");
List taskList = spContext.Web.Lists.GetByTitle("Tasks");

CamlQuery query = new CamlQuery();
query.ViewXml = String.Format(@"<View><Query></Query></View>");

taskCollection = taskList.GetItems(query);

MessageBox.Show(taskCollection.Count.ToString());

spContext.Load(taskCollection);
spContext.ExecuteQueryAsync(OnSuccess, OnFailure);
taskCollection değişkenine atama yaptıktan sonra hemen içerdiği eleman sayısını ekrana bastırmaya çalışıyorum. Bu işlem sırasında da yukarıdaki hatayı alıyorum. Neden? Daha önceki postumda da bahsettiğim gibi üzerinde işlem yapacağımız değişkenler ClientContext nesnesine yüklenir ve yüklenmesi içinde asenkron bir çağrı yapmak gerekir.

Peki bu taskCollection değişkeninin eleman sayısına ne zaman ulaşabilirsiniz? OnSuccess içerisinde derim ben de ;) Görelim;
private void OnSuccess(object sender, ClientRequestSucceededEventArgs e)
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(taskCollection.Count.ToString());
});
}
Operasyonu neden Dispatcher içinde yazdığımıza da yine daha önceki postumda değinmiştim.

Kolay gelsin,

Sharepoint 2010: Cannot complete this action. Please try again.

Sharepoint 2010'da Silverlight web part geliştirdiniz. Uygulamanız sırasında liste işlemleri yaparken sürekli bu hatayı alıyorsunuz;

Cannot complete this action. Please try again.

Hatanın nedeni %99 kullandığınız CAML query'den kaynaklanıyor. Kontrol edin. Ama insan evladı hata yapmaya çok meyillidir, özellikle konu CAML olduğunda :) Bu nedenle siz en iyisi U2U'nun ücretsiz Caml Builder tool'unu indirin, rahat edin.

Tool bile kullansanız CAML query hazırlarken dikkat etmeniz gereken önemli bir nokta var. O da View tag'leri. Sorgunuzu tool'da hazırladıktan sonra size en dışta Query tag'leri olan bir sorgu verir.
CamlQuery query = new CamlQuery();
query.ViewXml = String.Format(@"<Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>1</Value></Eq></Where></Query>");
Bunu Client Object Model çağrılarında direkt kullanamazsınız. Bu sorgunun başına ve sonuna taglerini eklerseniz sorgunuz kullanıma hazırdır.
CamlQuery query = new CamlQuery();
query.ViewXml = String.Format(@"<View><Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>1</Value></Eq></Where></Query></View>");
Bir dikkat etmeniz gereken nokta da tool'un verdiği sorguda çift tırnaklar bulunmasıdır. Bunu kod tarafına yapıştırırken çift tırnak yerine tek tırnak kullanmanız gerekmekte (içerik string olduğu için ).

Bunlara dikkat ederseniz sorgu hatalarınız minimuma inecektir ;)

Kolay gelsin,


12 Temmuz 2011 Salı

Client Object Model nedir? Sharepoint 2010'da Silverlight Web Part nasıl kullanılır?

Sharepoint portalları üzerinde bugüne kadar asp.net teknolojisiyle geliştirilmiş user controlleri web part olarak host edebiliyorduk. Sharepoint 2010'da da bu durum devam etti. Ancak güçlü görselllere sahip ve kısmen istemci tarafında çalışan Silverlight teknolojisini de Sharepoint'te bir şekilde çalıştırmak gerekiyordu. Vee bunun için Sharepoint 2010'da geliştirilmiş olan Client Object Model kavramı ortaya çıktı.

Bu model ile, Sharepoint 2010 üzerinde, xap uzantılı Silverlight uygulamalarımızı Silverlight web part olarak host edip, çalıştığı portaldaki listeler üzerinde istenilen işlemleri yapabiliyoruz. Biz Silverlight üzerinden, client object modeli kullanırken, o arka planda Xml ve JSON formatında servisler ile Sharepoint Object Model ile haberleşerek server side işlemleri bizim için yürütüyor. Bu makalede adım adım Client Object Model kullanarak Silverlight web part geliştirmeyi ve uygulamamızı host etmeyi göreceğiz.

  1. İlk adım olarak Visual Studio 2010'umuzda yeni bir Silverlight projesi ya da mevcut Sharepoint 2010 solution'ımız üzerinde yeni bir Silverlight projesi açıyoruz. Zaten bir SharePoint solution'ı olan developer'lar daha derli toplu olması açısından ikinci seçeneği tercih edebilir. Bu şekilde yapmak (Sharepoint projelerinde package mantığı olduğundan dolayı deployment'ı da kolaylaştıracaktır.). Ben örnekte ilk seçeneği kullanacağım. Projeyi oluşturduktan sonra ilk işimiz proje referanslarına %WINDIR%\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin klasörü altında yer alan "Microsoft.SharePoint.Client.Silverlight" ve "Microsoft.SharePoint.Client.Silverlight.Runtime" dll'lerini eklemek. Bu dll'leri kullanarak Client Object Model'i kullanacağız.
















  2. Dll'leri ekledikten sonra Silverlight uygulamamızı geliştirmeye başlayabiliriz. Örnek olarak portalımızda bir listede yer alan elemanları çekip listeleyen bir uygulamaya yapalım. Öncelikle xaml tarafında gerekli elemanları yerleştirelim.
    <UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"  x:Class="SLWebPart.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
    <StackPanel Orientation="Vertical">
    <Button x:Name="btnGorevGetir" Content="Tüm Görevleri Getir" Click="btnGorevGetir_Click"
    Width="200" Height="50"></Button>
    <sdk:DataGrid x:Name="taskGrid" AutoGenerateColumns="True" />
    </StackPanel>
    </Grid>
    </UserControl>
    Xaml tarafına sadece görevleri çekme komutunun verileceği bir buton ve çekilen görevlerin doldurulacağı bir dataGrid yerleştirdik.



  3. Code behind tarafında yapacağımız işlem ise şu. Görevleri getir komutunu verecek butonun Click event'inde, Sharepoint listesinden elemanların çekilmesi işlemi ve bunların dataGrid'e doldurulması. Bu noktada Client Object Model kullanımı devreye giriyor. Buton Click eventimizi görelim:
    private void btnGorevGetir_Click(object sender, RoutedEventArgs e)
    {
    ClientContext spContext = new ClientContext("http://t1wsportal01/TalepYonetimi/");
    List taskList = spContext.Web.Lists.GetByTitle("Tasks");

    CamlQuery query = new CamlQuery();
    query.ViewXml = String.Format(@"<View><Query></Query></View>");

    taskCollection = taskList.GetItems(query);
    spContext.Load(taskCollection);
    spContext.ExecuteQueryAsync(OnSuccess, OnFailure);
    }
    Öncelikle Client Object Model dll'leri içerisinde yer alan ClientContext nesnesini, listemizin yer aldığı portal adresimizle yaratıyoruz. Daha sonra bu nesne üzerinden listemizin adı olan Tasks key'ini kullanarak SP listemize ulaşıyoruz. (Yeri gelmişken liste adı değişince bu kod patlayacağı için liste adını kullanmak doğru bir yaklaşım değil. Bu olası sorunu engellemek için listelerin internal name'leri üzerinden bu işlemi yapmak daha doğru olur daha ileriki makalelerde ona da değinirim).

    Listemize ulaştıktan sonra sorguyu yapacağımız CAML query'i hazırlıyoruz. Örnekte tüm listeyi çekmek istediğimiz için sorgumuzun içinde ekstra bir condition yok gördüğünüz üzere, ancak condition olacak durumlarda bildiğiniz CAML sorgusu ile dönen sonuçları daraltmanız mümkün. (Burada dikkat edilecek nokta da caml query sorgusunun başına ve sonuna tag'larini eklemek, yoksa hata alıyorsunuz ;) )

    Listemiz elimizde. Sorgumuz da hazır. Peki şimdi? Liste üzerinden GetItems metoduyla ilgili sorgumuzu çalıştırarak global tanımladığımız bir ListItemCollection'a liste elemanlarımızı çekiyoruz. Neden global? Çünkü Client Object Model ve Silverlight uygulamalarında tüm çağrılar asenkron oluyor. Yani elemanları listItemCollection'ımıza çektikten sonra hemen okuyamıyoruz. Asenkron bir çağrı sonucunda okuma işlemini yapabiliyoruz. Bu nedenle de collection'ımızı global tanımlıyoruz.

    ListItemCollection'ımıza gerekli atamayı yaptıktan sonra da ClientContext nesnemize load işlemi yapıyoruz ve asenkron çağrımızı gerçekleştiriyoruz. Bu executeQuery metodunun senkron bir overload'u da vardır. Eee o zaman hemen kullanalım?! Yok canım olmuyor :) UI içeren Client Object Model uygulamalarımızda mecburen asenkron çağrıları kullanıyoruz. Ama ola ki Console uygulaması yaparsınız bir gün o zaman senkron çağrıyı kullanabilirsiniz ;)

    Asenkron çağrı metodunda dikkat ederseniz OnSuccess ve OnFailure diye iki adet callback metot kullandım. Bu metotlar da asenkron çağrı başarılı veya başarısız olması durumunda callback yapılacak metotları ifade ediyor. Yani bu şu demek, bizim asenkron çağrımızın başarılı olması durumunda listItemCollection'ımızı okuma ve grid'e doldurma işlemlerini OnSuccess'in içerisinde yapacağız demek. Görelim;
    private void OnSuccess(object sender, ClientRequestSucceededEventArgs e)
    {
    SuccessDelegate delegateMethod = success;
    this.Dispatcher.BeginInvoke(delegateMethod);
    }
    private void success()
    {
    try
    {
    List<Task> taskList = new List<Task>();

    foreach (ListItem item in taskCollection)
    {
    Task newTask = new Task();
    newTask.GorevID = Convert.ToInt32(item["ID"]);
    newTask.GorevAdi = Convert.ToString(item["Title"]);

    taskList.Add(newTask);
    }

    taskGrid.ItemsSource = taskList;
    }
    catch (Exception ex)
    {
    MessageBox.Show("Exception from success: " + ex.Message);
    }
    }

    Burada dikkat edilmesi gereken nokta tüm operasyonların Dispatcher.Invoke içerisinde yapılması gerekliliği. Ben de debugging kolaylığı olması açısından bir delegate metot tanımlayarak Dispatcher nesnesinden çağrısını yapıyorum. Asıl operasyonun yapıldığı success metodunda yapılan da gördüğünüz üzere çok basit. Asenkron çağrı sırasında doldurduğumuz global listItemCollection'ımızda dönerek istediğimiz liste kolon değerlerini kendi tipimize atıyoruz. Daha sonra da grid'e kendi tipimizden bir koleksiyonu bağlıyoruz.

    Tüm kodu görelim;
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using Microsoft.SharePoint.Client;

    namespace SLWebPart
    {
    public partial class MainPage : UserControl
    {
    ListItemCollection taskCollection;

    private delegate void SuccessDelegate();
    private delegate void FailDelegate(Exception ex);

    public MainPage()
    {
    InitializeComponent();
    }

    private void btnGorevGetir_Click(object sender, RoutedEventArgs e)
    {
    ClientContext spContext = new ClientContext("http://t1wsportal01/TalepYonetimi/");
    List taskList = spContext.Web.Lists.GetByTitle("Tasks");

    CamlQuery query = new CamlQuery();
    query.ViewXml = String.Format(@"<View><Query></Query></View>");

    taskCollection = taskList.GetItems(query);
    spContext.Load(taskCollection);
    spContext.ExecuteQueryAsync(OnSuccess, OnFailure);
    }

    private void OnFailure(object sender, ClientRequestFailedEventArgs e)
    {
    FailDelegate delegateMethod = fail;
    this.Dispatcher.BeginInvoke(delegateMethod, e.Exception);
    }

    private void fail(Exception ex)
    {
    MessageBox.Show("Exception from fail: " + ex.Message);
    }

    private void OnSuccess(object sender, ClientRequestSucceededEventArgs e)
    {
    SuccessDelegate delegateMethod = success;
    this.Dispatcher.BeginInvoke(delegateMethod);
    }

    private void success()
    {
    try
    {
    List<Task> taskList = new List<Task>();

    foreach (ListItem item in taskCollection)
    {
    Task newTask = new Task();
    newTask.GorevID = Convert.ToInt32(item["ID"]);
    newTask.GorevAdi = Convert.ToString(item["Title"]);

    taskList.Add(newTask);
    }

    taskGrid.ItemsSource = taskList;
    }
    catch (Exception ex)
    {
    MessageBox.Show("Exception from success: " + ex.Message);
    }
    }
    }
    }
    Kendi veri tipimiz olan Task sınıfı ise;
    namespace SLWebPart
    {
    public class Task
    {
    public int GorevID { get; set; }
    public string GorevAdi { get; set; }
    }
    }


  4. Evett. Silverlight uygulamamız tamamlandı. Şimdi bunu Sharepoint 2010'da Silverlight Web Part olarak nasıl host edeceğiz? Şimdi bunun için birkaç yöntem var. Ben bu makalede birine değineceğim. Öncelikle Portal'ımızda "Xap Library" adında bir doküman kütüphanesi yaratıyoruz. Document Template'ini de "None" olarak değiştirelim.












    Daha sonra bu yarattığımız doküman kütüphanesine, Silverlight uygulamamızın build çıktısı olan xap uzantılı dosyayı ekliyoruz. Kendisi proje klasöründe Bin/Debug içerisinde yer alır. Silverlight uygulamamızı derledikçe yeni .xap dosyasını buraya yükleyeceğimiz için yükleme adımı sırasında "Overwrite existing files" demeyi unutmuyoruz.













  5. Xap dosyasını portalımıza yükledikten sonra son aşama olan bunu web part olarak bir sayfada göstermek kaldı. Bunun için XapLibrary doküman kütüphanemizde ilgili xap dosyamızın "Name" kolonundaki bağlantısına sağ tıklayarak "Properties"i seçiyoruz.























    Yeni açılan ekranda yer alan "Address (URL)" e karşılık gelen değeri kopyalıyoruz.
























    Portalımızda Silverlight web part'ı host edeceğimiz sayfayı açıyoruz veya böyle bir sayfa yoksa All Site Content -> Site Pages -> Add new page yolunu izleyerek web part'ı host edeceğimiz bir sayfa yaratıyoruz. Yaratılan sayfada üst menüdeki Insert tabından Web Part'ı seçiyoruz.









    Web part menüsünde solda Media and Content tipini seçip, daha sonra sağda açılan menüden Silverlight Web Part seçeneğini seçerek Add yapıyoruz.







    Açılan pop up ekranda, daha önce kopyaladığımız xap dosyasının library adresini yapıştırıp Ok'liyoruz.


















    Zaten bu noktada xap adresinde bir problem yoksa Silverlight uygulamamız direkt olarak sayfa içerisinde açılacaktır.

Silverlight uygulamamızı Sharepoint 2010 üzerinde host etmek işte bu kadar. Uygulamamızı test etmek için oluşturduğumuz sayfayı açıyoruz ve web part üzerinde "Tüm Görevleri Getir" butonumuza basıyoruz. Tasks listemizde yer alan tüm görevlerin grid'imizde gösterildiğini görüyoruz;

















Kontrol etmek açısından portalımızdaki Tasks listesini açıyoruz ve orada da aynı elemanların varolduğunu görüyoruz.






Sharepoint 2010 üzerinde, Silverlight uygulamaları kullanarak listelere erişmek bu şekilde mümkün oluyor. Listelerden veri çekilmesinin yanı sıra liste elemanları için tüm CRUD operasyonları ve liste işlemlerini de Client Object Model kullanarak yapmak mümkün.

Diğer operasyonların da bazılarını anlatan msdn bağlantısından da konu hakkında daha geniş bir bilgi elde edebilirsiniz.

Kolay gelsin,

WP7 uygulamalarında Back tuşu nasıl iptal edilir?

WP7 işletim sistemi içeren telefonların standart donanımlarında bildiğiniz üzere 3 adet tuş var. Solda bir önceki ekrana dönülmesini sağlayan Back tuşu, ortada ana sayfaya dönülmeyi sağlayan Home tuşu ve en sağda Bing'de arama yapmamızı sağlayan Search tuşu.
























Bu soldaki Back tuşu bazen uygulama geliştiricilerin canını sıkabiliyor. Uygulama içerisinde bir akışınız varsa ve bir önceki sayfaya geri dönülmesini istemiyorsanız bu Back tuşunun basılma event'ini yakalayıp, geri dönüşü engellemeniz mümkün.

Yapılması da çok basit alında. Projemizin xaml tarafında en dıştaki katman olan PhoneApplicationPage kontrolünün Event'lerine baktığımızda BackKeyPress event'ini görüyoruz ve çift tıklayarak bu eventi code behind tarafında yaratıyoruz.



















Yaratılma sonrasında Xaml kodu:
<phone:PhoneApplicationPage
x:Class="WindowsPhoneApplication1.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" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" BackKeyPress="PhoneApplicationPage_BackKeyPress">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Onur'un Yeri"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Back Testi" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
</Grid>

</phone:PhoneApplicationPage>
Code behind tarafında ise, yeni yaratılan metot içerisinde Back tuşuna basıldığında ne yapılmasını istiyorsak onu yazıyoruz. Bu örnekte işlemin iptal edilmesini istediğimiz için e.Cancel = true işimizi görecektir.
using System.Windows;
using Microsoft.Phone.Controls;

namespace WindowsPhoneApplication1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}

private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
MessageBox.Show("Back tuşuna basamazsın kardeşim!");

e.Cancel = true;
}
}
}
Örnekte Back tuşuna basıldıktan sonra uygulamanın tepkisini görelim:
























İşte bu kadar basit bir şekilde Back tuşunun uygulamamız içerisinde fonksiyonalitesini değiştirmiş olduk. Duruma göre iptal işlemi değil de başka bir fonksiyon işletilmesi gerekirse de yine aynı event üzerinden istediğiniz akışı işletebilirsiniz.

Kolay gelsin,