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

15 Temmuz 2011 Cuma

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,

5 Temmuz 2011 Salı

Windows Phone 7 nedir? WP7'de nasıl uygulama geliştirilir?

Mobil uygulamaların şuan çok popüler olduğunu biliyorsunuz.. Ama Objective C, Java falan kasamıycam diyosunuz.. Zaten Macbook falan da almak lazım şimdi Emülatörle uğraşamam da dersiniz.. Eee Silverlight biliyorsunuz az çok! Ne duruyorsunuz mobil uygulama geliştirmek için?

Windows Phone 7.. Microsoft'un yeni nesil akıllı telefon işletim sistemi. Üzerinde uygulama geliştirmek için Silverlight bilmek yeterli! Bakalım nasıl kuruluyor:
  1. Windows Phone Developer Tools
  2. Windows Phone Developer Tools January 2011 Update
  3. Windows Phone Developer Tools Fix
Bunları indirip yükledikten sonra VS 2010'umuz açıyoruz. Ola ki bu noktada şu hatayı aldınız:

WP7 paketindeki herhangi bir yazılımın VS 2010 SP1 ile çalışmakta sorun yaşadığı anlamına geliyor. Bunu da aşmak için:

Control Panel --> Programs and Features --> Microsoft Visual Studio 2010 Service Pack 1 --> Uninstall/Change --> ReApply
MS Visual Studio 2010 SP1

yapmak yeterli. Sorunu aştıktan sonra VS 2010'umuzu açıyoruz ve Yeni Proje ekranında, sol menüde yeni bir arkadaşımız var artık: Silverlight for Windows Phone















Bu ekranda, Windows Phone Application seçerek yeni projemizi yaratıyoruz. VS 2010 geliştirme ekranı 2'ye bölünmüş olarak geliyor. Bir tarafta klasik xaml kodu, diğer tarafta xaml'de yaptığımız değişiklikleri anında görebileceğimiz WP7 ekranı.





















Hemen bir Hello World geliştiriyoruz.

Xaml:
<phone:PhoneApplicationPage
x:Class="TestWP7App.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">

<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="HELLO WORLD"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Giriş" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtName" Width="300" Height="80"></TextBox>
<Button x:Name="btnHello" Content="Selam" Width="150"
Height="80" Click="btnHello_Click"></Button>
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="txtResult" Width="300" Height="80"
TextAlignment="Center" FontSize="50"></TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
Designer Görünümü:
























Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

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

private void btnHello_Click(object sender, RoutedEventArgs e)
{
string isim = txtName.Text.Trim();
txtResult.Text = "Hello " + isim;
}
}
}

Derledikten sonra yapmamız gereken uygulamamızı test etmek. Ama henüz Türkiye'de satışa çıkmadığı için elimizde WP7 işletim sistemi içeren akıllı telefon yok :( Yılmayınız! Testimizi Developer Tools içerisinde gelen Emülatör üzerinde yaparız, müsterih olun.. Bunun için Standart Bar'dan Windows Phone 7 Emulator seçimini yaptıktan sonra Proje --> Deploy yapmanız yeterli.




Deploy işlemini yaptıktan sonra emülatör otomatik olarak açılacak ve sırayla aşağıdaki ekranlar gelecek:




















Bu ekranda uygulamamızı seçtiğimizde de geliştirdiğimiz uygulamamız açılacak. Testimizi artık gerçekleştirebiliriz:

Emülatör testi sırasında karakter girişi yapılacak textbox gibi alanlara tıklandığında otomatik olarak sanal klavye çıkıyor örnekte de görüldüğü üzere. Karakter seçimi de bu sanal klavye üzerinden fare kullanarak yapılıyor. Sanal klavye çok tatlı görünse de sık yapılan testlerde bir noktadan sonra tek tek karakter seçmek insanı bayıyor. Bunun için de Page Up/ Page Down tuşları ile sanal klavye / normal klavye geçişini sağlayabilirsiniz ;)

Gördüğünüz gibi çok basit bir şekilde ilk Mobil uygulamanızı geliştirdiniz. Tebrikler!

Ben Microsoft'un verdiği kontrollerle yetinemem, daha fazla isterim diyenler için de insanlar boş durmamış:
  1. Silverlight For Windows Phone Toolkit (Ücretsiz, codeplex'te)
  2. Telerik RadControls for Windows Phone 7 (Ücrete tabii)

Olur da bir şekilde WP7 içeren akıllı telefon edinirseniz, telefon üzerinde uygulamanızı çalıştırmak için development makinenize Zune Software yüklemeniz yeterli. Telefonunuz data kablosuyla development makinenize bağladıktan sonra, VS 2010'dan deploy ederken Standart Bar'dan bu sefer Windows Phone 7 Emulator yerine Windows Phone 7 Device seçerek deployment yapacaksınız. Zune Software arka planda çalışarak sizin için gerekli deployment işlemini gerçekleştirecek. Yalnız bu şekilde uygulama atmanın problemi, bir süre sonra uygulamanın telefondan silinmesi (sanırım demo gibi bir kapsamda sayılıyor). Genel bir dağıtım için de WP7'de henüz bir güzelliği yok Microsoft'un. Bunun için Ekim ortasında release olacak olan bir sonraki sürüm 7.1 yani Mango'yu beklemek gerekecekmiş (Daron Yöndem öyle söyledi).

WP7 girişi için şimdilik söyleyeceklerim bu kadar, umarım süper uygulamalar geliştirmenizde bir katkım olmuştur ;)