Ana Sayfa | English Blog | Seminer TV | Dil Cookie Sil  Blog'u Mail ile takip et!       
Daron Yöndem - October, 2008
bir yazılımcının tasarıları...
 Friday, October 31, 2008

Bugün Fatih Üniversitesi'nde Silverlight ve WPF anlattım. Gerçekten çok sıcak bir atmosfer vardı üniversite içerisinde, kendimi bir an bir üniversitede olduğuma ikna etmem gerekti :) Ben mi yanlış yerden girdim bilmiyorum ama hemen girişte bir mısırcı bir de ananas zaten seyyar satıcı kıvamında iç mekan işportalarından :) görünce (son dönemde bunlar moda zaten) epey şaşırdım diyebilirim. Öğrenciler adına sevindim tabi ki.

Fatih Üniversitesi Silverlight ve WPF Seminerleri
Fatih Üniversitesi Silverlight ve WPF Seminerleri

İlginç anlar yaşadığım hatıralar edindiğim bir seminer oldu. WPF örneği olarak Yahoo Mesenger'ı gösterirken IBM'den sevgili dostum Arden'in mesaj atıp "En büyük IBM" demesinden tutun :) Dinleyici arkadaşlardan birinin "3D nedir?" sorusuna kadar (hala bu sorunun ciddi mi şaka mı olduğunu anlamış değilim:D) hoş anlar yaşadım diyebilirim.

Aktivitenin organizasyonunda özellikle sevgili Muhammed Medeni Baykal, Ahmet Aydin, Bilgehan Berberoglu, Umit Samimi, Erdin Sarpkaya ve Ahmet Eralp'e çok teşekkür ediyorum.

Hepiniz kalın sağlıcakla ;)

Friday, October 31, 2008 11:53:56 AM (GTB Standard Time, UTC+02:00)  #    Comments [3]   Seminer | Silverlight 2.0 | WPF  | 
 Thursday, October 30, 2008

Visual Studio 2010 ve .NET Framework 4.0 CTP'lerinin yayınlandığı bugünlerde iki yol sonra karşımıza çıkacak yazılım teknolojilerine yön verme ve inceleme adına heyecanlı günler yaşadığımı itiraf edebilirim.

Visual Studio 2008 ve .NET Framework 4.0 yeni logoları.
Visual Studio 2008 ve .NET Framework 4.0 yeni logoları.

Tüm bu yenilikler arasında tabi ki Visual Basic'in de artık 10'uncu sürümü ile karşı karşıyayız. Bu yazıa şu an yayında olan CTP üzerinden yola çıkarak VB 10 ile beraber gelen yenilikleri inceleyeceğiz.

Statement Lambda

Lambda'lara az çok LINQ ile beraber alışmıştık. VB 10 ile beraber çok ilginç ve bir o kadar da güzel bir özellik geliyor. Ama gelin bunun öncesinde VB 9 ile neler yapardık bir göz atalım.

[VB9]

Public Class Form1

 

    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        MsgBox("Burada")

    End Sub

 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        AddHandler Me.Click, AddressOf Form1_Click

    End Sub

End Class

Gördüğünüz gibi basit bir şekilde Form'un Load durumunda dinamik olarak yine formun Click event'ını bir Sub'a bağlıyoruz. Böylece artık forma tıklandığında "Burada" mesajı gösterilecek. Tüm bunu yapmak için, yani dinamik event bağlamak için gidip ayrı bir yerde Sub yazmamız ve sonra da AddressOf ile bağlamamız gerekiyordu. Oysa artık satır için Sub var :)

[VB10]

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        AddHandler Me.Click, Sub()

                                                     MsgBox("Burada")

                                            End Sub

    End Sub

End Class

Nasıl? Güzel değil mi? Satır içi Sub'ımızı yazdık bitti. Bu işlevselliği AddressOf'u kullandığınız her yerde kullanabileceğinizi düşünürseniz gerçekten süper! Peki ya Function'lar? İşte size satır içi Function kullanımı.

[VB10]

        Dim Fonksyon = Function(x As Integer)

                                           Return x * 2

                                  End Function

        MsgBox(Fonksyon(2))

Yukarıdaki kod içerisinde doğrudan Function'ımızı kodun içinde satır içi yazarak tanımlıyoruz ve sonrasında da rahatlıkla Invoke işlemini gerçekleştirebiliyoruz.

Coşmuş Type Inference

Type Inference'a zaten alışkın durumdayız. VB10 ve VS10 ile beraber bir adım daha ileriye gidiliyor. Örneğin aşağıdaki gibi bir değişken tanımında değişkenin bir Array olduğunu veya ne Array'i olduğunu belirtmenize gerek kalmıyor.

Type Inference'ın bu kadarı :)
Type Inference'ın bu kadarı :)

Unutmayın bu şekilde tanımlamalar performans kaybına neden olmaz. Compiler Compile Time'da gerekli kodları üretecektir.

PLINQ

Parallel LINQ aslında VB'ye özel bir konu değil fakat VS10 ve VB10 ile beraber de geldiği için hızlıca bahsetmek istiyorum. Adından da anlaşılacağı üzere PLINQ'de çalıştırılan sorguların kendi içlerinde birden çok işlemcide çalıştırılmak üzere hazırlanmış durumdalar. Gelin hemen aşağıdaki koda bir göz atalım.

[VB10]

       Dim sayilar = {10, 20, 30, 40}

 

        Dim XML = <Sayilar>

                             <%= From Inc In sayilar.AsParallel

                                      Select <Sayi><%= Inc %></Sayi> %>

                           </Sayilar>

AsParallel metodu otomatik olarak PLINQ kullanılmasını sağlıyor. Normal şartlarda sırası ile 10, 20, 30, 40 sayılarını alırken bu şekilde AsParallel olarak sorgumuzu çalıştırdığımızda 20, 10, 30, 40 gibi bir sonuç elde ediyoruz. Bunun nedeni işlemin paralel bir şekilde çalıştırıldıktan sonra sonucun bize döndürülüyor olması. Bu ufak detay bile aslında PLINQ'in kullanılabileceği ve kullanılamayacağı noktalara karar vermek için yeterli sayılabilir.

Add metodunu defalarca kullanmaktan kurtulunu!

Bu özelliğe başlık bulmakta zorlandığımı sanırım farkına vardınız. Düşünün ki elimizde bir List var ve bu List içerisinde birden çok Item eklememiz gerekiyor. Normal şartlarda her bir Item'ı yaratarak tek tek Add metodunu çağırırdık.

[VB9]

Dim Liste As New List(Of String)

Liste.Add("Ahmet")

Liste.Add("Mehmet")

Peki VB10 tarafında neler yapabiliriz? Yeni bir Keyword'ümüz var : From

[VB10]

 Dim Liste As New List(Of String) From {"Ahmet", "Mehmet"}

Aslında arka planda çalışan yapı doğrudan dizi içerisindeki bir Item için Add metodunu çağırmaktan farklı değil. Örneğin elimizde özel bir sınıfın listesi olsaydı aynı şekilde o sınıftan da objeler yaratarak from ile listeye ekleyebilirdik.

[VB10]

        Dim Liste As New List(Of Adam) From {

            New Adam() With {.Adi = "Ahmet", .Soyadi = "Hebe"},

            New Adam() With {.Adi = "Mehmet", .Soyadi = "Hebe"}}

Örnek kodumuzdaki List bir Adam List'i olduğu için burada önemli olan List sınıfının Add metodunun Adam tipinden değişken istiyor olması. Sırasıyla yaratarak bir array olarak veriyoruz. İsterseniz Adam tipinden List'elerin Add metoduna Overrides keywordü ile bir alternatif eklemek için ExtensionMethod'ları da kullanabilirsiniz.

[VB9]

Module Module1

    <Runtime.CompilerServices.Extension()>

    Sub Add(ByVal x As List(Of Form1.Adam), ByVal Adi As String, ByVal soyadi As String)

        x.Add(New Form1.Adam() With {.Adi = Adi, .Soyadi = soyadi})

    End Sub

End Module

VB9'da tanıştığımız Extension Method'lardan bir adet tanımlayarak Adam tipinden bir Liste oluşturulduğunda bu objelerin bir Add metodlarının olacağını ve Adi, Soyadi olarak String'ler alacağını tanımlıyoruz. Extension Method içerisinde de bu bilgileri alıp yeni bir Adam yaratıp listeye ekliyoruz. Böylece artık elimizdeki listeye Adam eklemek için Add metodunu çağırırken iki adet String verip bir Adam eklenmesini de sağlayabildik. Ama aslında bu Add metodunu da biz değil From keyword'ü kullanacak.

[VB10]

        Dim Liste As New List(Of Adam) From {

            {"Ahmet", "Hebe"},

            {"Mehmet", "Hebe"}}

Böylece artık yukarıdaki kodumuzda doğrudan bilgileri vererek her seferinde New ile obje yaratmadan da istediğimiz kadar Adam ekleyebiliriz.

Property tanımlamaları

C#'dan en çok kıskandığım özelliklerden biri Get ve Set'lerin kısaltılmasıydı. Çoğu zaman Property tanımlarken aslında Get ve Set kodlarını değiştirmiyoruz. Her ne kadar VS içerisinde kısa yolları kullanarak bu kodları yazmıyor olsak da maalesef biz yazmamış olsak da projemizdeki her satır kodun bir gün bir bug olarak karşımıza çıkma ihtimali var :)

[VB9]

Private PAdi As String = "Varsayılan"

Public Property Adi() As String

    Get

        Return PAdi

    End Get

    Set(ByVal value As String)

        PAdi = value

    End Set

End Property

"Eskiden" kelimesini kullanmak için daha erken olsa da maalesef Property'leri VB9'da yukarıdaki şekilde tanımlıyorduk.

[VB10]

        Public Property Adi As String = "Varsayılan"

Sanırım bu kodun üzerine daha fazla söz söylemeye gerek yok.

Son sürpriz!

Yukarıdaki kodlar dikkatinizi çekmediyse ufak bir ipucunda buluniyim. Tek satırda yazılması gereken kodları çoklu satırlı olarak yazarken bir değişiklik görebiliyor musunuz?

[VB9]

        Dim Liste2 As New List(Of Adam) From { _

            {"Ahmet", "Hebe"}, _

            {"Mehmet", "Hebe"}}

[VB10]

        Dim Liste As New List(Of Adam) From {

            {"Ahmet", "Hebe"},

            {"Mehmet", "Hebe"}}

Benim sanırım en çok sevindiğim gelişmelerden biri bu oldu. Artık uzun uzun tek satırda kod yazmak zorunda değiliz veya her satır atlamak istediğimizde _ alt çizgi ile alt satıra geçme zorunluluğu da yok! C#'dan en çok kıskandığım özelliklerden biri de buydu.

VB kolayın kullanımını arttırarak kuvvetli bir dil olarak var olma yolunda tam gaz devam ediyor. Gelişmeler çok sevindirici. Bakalım 2010'a kadar karşımıza çıkacak diğer CTP'lerde neler olacak.

Hepinize kolay gelsin.

Thursday, October 30, 2008 8:16:03 PM (GTB Standard Time, UTC+02:00)  #    Comments [9]   Visual Basic 2010  | 
 Wednesday, October 29, 2008

Sonunda söz verdiğim gibi elime ulaşan tüm INETA Capital Hit fotoğraflarını sizlerle paylaşıyorum. Aşağıdaki adresten tüm fotoğraflara ulaşabilirsiniz. Hala elinde fotoğraf olanlar bana mail atabilirler, mail atılamayacak boyutta fotoğrafları olanlar da yine mail atarlarsa fotoğrafları yükleyebilecekleri FTP alanları da sağlayabilirim.

http://cid-e780a156a6bd0e34.skydrive.live.com/browse.aspx/INETA%20Capital%20Hit%202008 

Ayrıca bir de DeepZoom projesi hazırladım :) Tabi biraz mofikasyon ile hafif bir 3D ortam yaratmak da hoş oldu. Projenin çalışır halini aşağıda inceleyebilirsiniz. "Kıvırt" düğmesine dikkat :) Ayrıca fotoğraflara siz yaklaştıkça arkadakileri görebilmeniz adına fotoğraflar teker teker görünmez olacak. "Ölümüne detay" CheckBox'ını işaretlerseniz fotoğrafların tüm detaylarına kadar zoom yapabilirsiniz.

Biliyorum nasıl oldu bu iş diyorsunuz? :) Buyurun sizinle yukarıdaki projenin kaynak kodlarını da paylaşıyorum. Siz de kullandığınız yerleri benle paylaşırsanız çocuğunun ilk "baba" deyişini duyan baba gibi sevinebilirim :)

3D DeepZoom Projesi Kaynak Kodları29102008_1.rar (50,57 KB)

Hepinize kolay gelsin.

Wednesday, October 29, 2008 3:27:32 PM (GTB Standard Time, UTC+02:00)  #    Comments [4]   Seminer | Silverlight 2.0  | 
 Tuesday, October 28, 2008

Silverlight 2.0 ile beraber gelen kontrol sayısı 1.0'a kıyasla ciddi miktarda arttı. Fakat hala eksikler var! İşte bu eksikleri Silverlight sürümleri arasında doldurabilmek adına yeni bir proje CodePlex üzerinde yayında. Proje aslında uzun süredir geliştiriliyor. Fakat daha yeni yeni stabil kontroller sunmaya başladı. Aslında eski AJAX Control Toolkit'e benzetebileceğimiz bir yapıda ilerleyen Silverlight Toolkit unutmamak gerek ki doğrudan Microsoft tarafından geliştirilmiyor, tamamen açık kaynak kodları ile gönüllü programcılar tarafından ilerletilen bu projede bazı kontroller stabil olarak işaretlenmişken bazıları ise hala "Preview" konumundalar.

İşte bu kütüphane içerisinde stabil olarak işaretlenmiş olan kontrollerden belki de en acil ihtiyaç duyacağımız TreeView kontrolünü bu yazımızda inceleyeceğiz.

Nasıl yüklenir?

Silverlight Toolkit içerisinde kontrollerden herhangi birini kullanabilmek için ilk olarak tabi ki söz konusu kütüphaneyi CodePlex üzerinden indirmeliyiz. Hemen aşağıdaki adresten son paketi indirebilirsiniz;

http://www.codeplex.com/Silverlight/Release/ProjectReleases.aspx?ReleaseId=18804

Paketi bilgisayarınıza indirdiğinizde Binaries klasörü içerisinde bulunan Microsoft.Windows.Controls.dll dosyasını yeni yarattığınız bir Silverlight projesine Visual Studio içerisinde referans olarak eklemeniz gerekiyor. Paket içerisinde bulunan diğer DLL'lere ve dosyalara ileriki makalelerimizde değineceğiz.

Unutmayın, referans ekleme işlemini doğrudan Silverlight projenize yapmanız gerek. Silverlight projenizle aynı Solution içerisinde bulunan ASP.NET proje ile herhangi bir ilişkimiz yok.

Bu işlemi tamamladıktan sonra artık Expression Blend tarafına geçerek kontrollerimizi kullanmaya başlayabiliriz. Eğer Expression Blend ile değil de Visual Studio tarafında XAML kodlarını yazmak isterseniz tek tek XAML içerisinde NameSpace tanımlarını yapmanız gerekecektir.

Expression Blend ile projemizi açtıktan sonra "Asset Library"e gidip "Custom Controls" tabına geçtiğimizde TreeView kontrolü karşımıza çıkıyor.

TreeView kontrolü Expression Blend içerisinde karşımıza çıkıyor!
TreeView kontrolü Expression Blend içerisinde karşımıza çıkıyor!

TreeView kontrolünü Blend içerisinde projenizde herhangi bir XAML dosyasına eklediğinizde XAML koduna dönüp bakarsanız aşağıdaki şekilde gerekli NameSpace tanımlarının da yapılmış olduğunu göreceksiniz. Eğer Blend kullanmasaydık bu işlemleri Visual Studio içerisinde elle yapmamız gerekecekti.

[XAML]

<UserControl x:Class="SilverlightApplication7.Page"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  Width="400" Height="300" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">

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

 

      <controls:TreeView Margin="74,43,133,137"/>

 

    </Grid>

</UserControl>

Nasıl kullanılır?

Bir TreeView aslında birden çok TreeViewItem içerir. İsterseniz bu TreeViewItem'ları doğrudan Expression Blend içerisinde sürükle & bırak tekniği ile TreeView içerisine yerleştirebileceğiniz gibi isterseniz doğrudan kod ile databind işlemleri de yapabilirsiniz.

[XAML]

      <controls:TreeView Margin="74,43,133,137">

        <controls:TreeViewItem Header="Deneme1"/>

        <controls:TreeViewItem Header="Denem 2"/>

        <controls:TreeViewItem Header="Deneme 3">

          <controls:TreeViewItem Height="100" Width="100" Header="İçinde!"/>

        </controls:TreeViewItem>

      </controls:TreeView>

Yukarıdaki kod içerisinde birden çok TreeViewItem içeren bir TreeView görüyorsunuz. TreeView altında toplam üç adet TreeViewItem varken son TreeViewItem içerisinde bir tane daha TreeViewItem var. Böylece iç içe açılarak devam eden sonsüz döngüde bir ağaç yapısı oluşturmak mümkün.

TreeViewItem'ların Header özelliğine gözükecek metin değerini girebileceğiniz gibi aslında farklı Silverlight kontrollerini de Header içerisine koyma şansınız var.

[XAML]

      <controls:TreeView Margin="74,43,133,137">

        <controls:TreeViewItem Header="Deneme1"/>

        <controls:TreeViewItem Header="Denem 2"/>

        <controls:TreeViewItem Header="Deneme 3">

        <controls:TreeViewItem Height="100"

                              Width="100">

          <controls:TreeViewItem.Header>

            <Image Height="50"

                  Width="50"

                  Source="Tree.jpg" />

          </controls:TreeViewItem.Header>

        </controls:TreeViewItem>

        </controls:TreeViewItem>

      </controls:TreeView>

Yukarıdaki kod içerisinde de görebileceğiniz gibi TreeViewItem'lardan birinin Header'ında bir Image nesnesi, yani fotoğraf var. Siz uygulamalarınızda farklı fantaziler yaparak isterseniz MediaElement aracılığı ile video bile koyabilir veya belki de TreeView içerisine bir DataGrid veya Calendar bile koyabilirsiniz.

Gelelim tüm bu işlemlerin kod ile nasıl yapıldığına. Varsayalım elimizde TreeView'de göstermek istediğimiz bir veri var. İlk olarak bu veriyi uygun şekilde düzenlememiz gerek. Bizim örneğimizde Fiyati ve Adi gibi özelliklere sahip bir sınıf kullanalım. Her bir TreeViewItem bu sınıf üzerinden oluşturulacak.

[VB]

    Class Urun

 

        Private PAdi As String

        Public Property Adi() As String

            Get

                Return PAdi

            End Get

            Set(ByVal value As String)

                PAdi = value

            End Set

        End Property

 

        Private PFiyati As Integer

        Public Property Fiyati() As Integer

            Get

                Return PFiyati

            End Get

            Set(ByVal value As Integer)

                PFiyati = value

            End Set

        End Property

 

        Private PList As List(Of Urun)

        Public Property Liste() As List(Of Urun)

            Get

                Return PList

            End Get

            Set(ByVal value As List(Of Urun))

                PList = value

            End Set

        End Property

 

        Public Sub New()

            Me.PList = New List(Of Urun)

        End Sub

    End Class

[C#]

        public class Urun

        {

            public string Adi { get; set; }

            public int Fiyati { get; set; }

            public List<Urun> Liste { get; set; }

 

            public Urun()

            {

                this.Liste = new List<Urun>();

            }

        }

Gördüğünüz gibi sınıfımızın Adi ve Fiyati özellikleri haricinde bir de List tipinden Liste adında Property'si var. Bunun nedeni aslında çok basit. Her bir TreeViewItem'ın kendi içinde birden çok TreeViewItem olabilir demiştik. Bizim her bir ürünümüzün için de bu şekilde birden çok ürün saklanabiliyor olacak. Verimizi bu şekilde üretip TreeView'e DataBind ettiğimizde TreeView geri kalanı halledecek.

Gelin şimdi de bizim için deneme amaçlı olarak geçici veri yığını yaratacak bir kod yazalım.

[VB]

    Function Veriyarat() As List(Of Urun)

        Dim Liste As New List(Of Urun)

        For x As Integer = 0 To 10

            Dim BirUrun = New Urun With {.Adi = "Ürün" & x, .Fiyati = Rnd() * 1000}

            For y As Integer = 0 To 5

                BirUrun.Liste.Add(New Urun With {.Adi = "Ürün" & y, .Fiyati = Rnd() * 1000})

            Next

            Liste.Add(BirUrun)

        Next

        Return Liste

    End Function

[C#]

       public List<Urun> Veriyarat()

        {

            Random RastGele = new Random();

            List<Urun> Liste = new List<Urun>();

            for (int x = 0; x <= 10; x++) {

                Urun BirUrun = new Urun { Adi = "Ürün" + x.ToString(), Fiyati = RastGele.Next(0,1000) };

                for (int y = 0; y <= 5; y++) {

                    BirUrun.Liste.Add(new Urun { Adi = "Ürün" + y.ToString(), Fiyati = RastGele.Next(0, 1000) });

                }

                Liste.Add(BirUrun);

            }

            return Liste;

        }

Kodumuz içerisinde toplam 10 adet içerisinde 5'er ürün bulunan ürün yaratılıyor. Şimdi tüm bu listeyi alarak doğrudan TreeView'ın ItemsSource özelliğine aktaracağız. Siz örneklerinizde farklı sınıflar ve farklı veri kaynakları kullanabilirsiniz. Özellikle LINQ2SQL veya Data Services kullandığınızı düşünürsek zaten elinize bu şekilde hazır nesneler gelecektir.

[VB]

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Agac.ItemsSource = Veriyarat()

    End Sub

[C#]

        public Page()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            Agac.ItemsSource = Veriyarat();

        }

Veri bağlantımızı yaptık. Fakat bu TreeViewItem'lar nasıl yaratılacak? Fiyati ve Adi adındaki özelliklerin içindeki değerler nerede gösterilecek? İşte bu noktada XAML tarafına geçerek bir ItemTemplate düzenlememiz gerekiyor. Böylece TreeView kendisine bağlanan veriye göre TreeViewItem'lar yaratırken nasıl bir görsellikten yola çıkacağını ve bu görsellik içerisinde gelen veriden hangi değerlerin nerelere yerleştirileceğini anlayabilecek.

[XAML]

    <controls:TreeView Margin="74,43,133,137"

                      x:Name="Agac">

      <controls:TreeView.ItemTemplate>

        <controls:HierarchicalDataTemplate ItemsSource="{Binding Liste}">

          <StackPanel Orientation="Horizontal">

            <TextBlock Text="{Binding Adi}"

                      Margin="5,0,0,0"

                      HorizontalAlignment="Left"

                      FontSize="10" />

            <TextBlock Text="{Binding Fiyati}"

                      Margin="5,0,0,0"

                      HorizontalAlignment="Left"

                      FontSize="10" />

          </StackPanel>

        </controls:HierarchicalDataTemplate>

      </controls:TreeView.ItemTemplate>

    </controls:TreeView>

Yukarıdaki XAML kodu ile aslında uygulamamızı sonlandırmış olduk. Peki neler yaptık? İlk olarak TreeView'ın ItemTemplate'i içerisinde yine Toolkit içerisinden gelen HierarchicalDataTemplate nesnesini yerleştirdik. Bu nesne bizim kod tarafında yarattığımız nested yapıyı algılayarak iç içe TreeViewItem'ların yaratılmasını sağlayacak fakat DataBind yaptığımız sınıfların hangi Property'sinin başka nested TreeViewItem'ların verilerini sakladığını anlayabilmesi için söz konusu Property'nin adını vermemiz lazım. Hatırlarsanız bizde Urun sınıfının Liste adında bir property'si vardı ve tüm alt öğeleri o saklıyordu. Biz de burada HierarchicalDataTemplate 'e ItemsSource olarak Liste'yi Bind ediyoruz. Geri kalanı kendisi halledecektir.

HierarchicalDataTemplate içerisinde doğrudan her bir TreeViewItem'ın Header bilgisini girer gibi istediğiniz Silverlight kontrollerini kullanabiliyorsunuz. Burada yapacağınız tasarım her TreeViewItem için kullanılacaktır. Tabi bunu yaparken Binding'lerimizi de unutmuyoruz ve yerine göre Fiyati ve Adi özelliklerini istediğimiz kontrollerin istediğimiz özelliklerine Bind ediyoruz. Bizim örneğimizde bir StackPanel içerisinde Fiyati ve Adi özelliklerini gösterecek iki farklı TextBlock bulunuyor.

DataBind TreeView örneğimiz bitti.
DataBind TreeView örneğimiz bitti.

Tüm verimizi bağladığımıza göre yeri geldiğinde seçili öğeyi nasıl yakalarız? Her bir TreeView'ın kendi SelectedItemChanged event'ı var. Bu event çalıştığında söz konusu TreeView'ın SelectedItem özelliğinden seçili öğeyi alabilirsiniz. En önemlisi SelectedItem size aslında DataBind esnasında bağlanan verinin içerisinde bulunan nesneyi döndürüyor. Yani bizim örneğimizde SelectedItem'ı aldığımda elimize Urun tipinden bir nesne gelecek. Gönül daha ne ister? :)

Hepinize kolay gelsin.

Tuesday, October 28, 2008 4:35:54 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]   Silverlight 2.0  | 
 Monday, October 27, 2008

Web ortamında herhangi bir şeyin yayınını yapanlar arasında ilginç bir sidik yarışı var :) Yok efendim senin siten alexa.com'da kaçıncı sırada, yok Google PageRank'in bilmem kaç... Bu muhabbetlerin "Benim babamın arabası 240 basıyor ya seninki?" den bir farkı varsa lütfen dürtün beni:)

Peki diyeceksiniz ki senin derdin ne şimdi? :) Bundan birkaç ay önce birilerinin bariz gazına gelerek :) blograzzi.com'a üye oldum ve blogumu oraya ekledim. Aslında o noktada gaza gelmekten öte düşündüğüm şey "Belki blogumdan haberdar olmayan ve faydalanabilecek birileri varsa onlar da bu vesile ile haberdar olur ve faydalanır" şeklindeydi. Bugün blog istatistiklerime baktığımda pek öyle bir etki göremiyorum, tabi arada sadece 5-6 kişi kazandıysam bilemeyeceğim, o da çok yeterli bir rakam aslında. Her neyse, blograzzi'ye göre Türkiye'nin en çok ziyaret edilen ilk 20 blogunda benimki de var.

Hooop! Bir dur bakalım!

Son paragraftaki cümlem tamamen kolpadır :) Neden mi? Evet doğrudur, ilk 20'de benim blogum da var ama hangi ilk 20? Türkiyenin? Yoo alakası yok. Benim blogum blograzziye üye değilken ben Türkiye'de değil miydim? Değinmeye çalıştığım nokta ilk 20'ye girenlerin kendilerini Türkiye'nin XXX'i zannederken aslında sadece kendi hayali blograzzi üyeleri dünyasında ilk 20'de oldukları. Bu arada blograzzi ile alıp veremediğim bir şey yok, anlamadığım şey insanların gereksiz gazları ve sidik yarışları. Tabi bir de üzerine bunlardan habersiz reklamcılar, pazarlama (uzmanları).

Alexa.com mu?

Hayatımda karşılaştığım en "kolpa" ve bir o kadar ciddiye alınan sitelerden biri de alexa! Dediklerine göre Alexa ranklerine göre sitelere reklam veren kurumlar bile var! Bu insanların cidden IT'den haberleri yok, işte canım ülkemde IT işini non-IT marketingciler yaparsa böyle olur. Birincisi Alexa'nın istatistiklerini topladığı en önemli öğe kendi Toolbar'ıdır ve bu Toolbar bugünün en popüler işletim sistemi Vista'da çalışmamaktadır :) Yani Alexa beni adam yerine koymuyor! Hatta son bir yıldır yeni laptop alıp beraberinde gelen işletim sistemini kullanan kimseyi kayda aldığı falan yok Alexa'nın! Eeee peki o zaman bana ne Alexa'nın fikrinden! Bu arada isteyenler nette bir aratsın Alexa Booster diye Proxy üzerinden pingler atarak Alexa Rank'inizi yükseltir, denenmiş, test edilmiş, onaylanmış hatta bu hizmet 6 yıl önce şirket tarafında bir müşterimize satılmıştır :) Geçmişler olsun!

Technorati mi?

Kaç kişi sizin blogunuza link vermiş? Kaç tane vermiş? Aslında bu soruların cevapları sitenizin popülerliliği ile ilgili çok ciddi ipuçları verebilir fakat biz Türk'üz! :) Link satış piyasası var! Bu Google PageRank için de geçerli. Beyaz fon üzerine beyaz yazı ile linkler konuyor sitelere :) (Herhalde CSS'de display:none kodunu bilmiyorlar) hadi onu bırakın ufacık yazı içi linkler konuyor para karşılığı! Böylece benim bloguma daha fazla link var benimki daha çok okunuyor! Hay Allah'ım ya! Cidden işimiz gücümüz yok bu mudur yani?

Peki neden?

Özellikle şu son katıldığım Google seminerleri sonrasında bu olayları daha net anlama şansım oldu. İnsanlar içerik paylaşmak veya faydalı olmak derdinde değiller. Sadece para kazanmaya çalışıyorlar. O nedenle her ne daha çok okunur ise onu yazıyorlar, her ne daha çok seyredilir ise onu gösteriyorlar ve reklam taktikleri ile internette reklam yayınlayan kurumları sömürüyorlar. Kurunun yanında yaşı da yaktığımın farkındayım. Tüm bunları neden yazdım? Dün biri bana "hocam sen Dertli Kerem yazılarını arttırsan senin blog daha çok okunur, teknik yazıları kimse anlamıyor" dedi :) Tabi arkadaşımı anlıyorum "İnsan kendisi neyse karşısındakini de öyle sanırmış!". Maalesef arkadaş kendisi anlamadığı için herkes anlamıyor sanıyor ama ben bana gelen maillerden kiminle muattap olduğumu çok iyi biliyorum! İkincisi; biliyorum, teknik olmayan yazılarım (Örn:Dertli Kerem serisi) daha çok yorum alıyor çünkü bunlar üzerine daha çok konuşulabilir konular! SQL'den veri çekmeyi anlattığımda eğer konuyu anladıysanız üzerine ne yorum yapabilirsiniz ki? "Hocam valla helal olsun böyle SELECT çekenini görmedim!" falan mı yazacak insanlar?

Arkadaşlar benim olayım belli, ilgilendiğim şeylerle ilgili bildiklerimi paylaşırım elimden geldiğince. En paylaşılmayanı paylaşıp katma değeri yüksek tutmaya çalışırım. Keyif almadığım işi salt sizin hoşunuza gidecek diye yapmam, üzgünüm! Bir keyif alınacaksa hep beraber alırız, tadından yenmez! Öyle milyonlarca kişi girsin yazılarımı okusun derdim de yok, bilen bilir, okuyan okur, kalan sahalar bizimdir! Alakasız tipi de sevmem, istemem! Sinirlendirmeyin adamı! :) Offf :D Dertli Kerem oldum sonunda valla...

Hepiniz kalın sağlıcakla...

Monday, October 27, 2008 12:34:52 AM (GTB Standard Time, UTC+02:00)  #    Comments [12]   Dertli Kerem  | 
 Sunday, October 26, 2008

INETA Capital Hit ile ilgili bilenlerin özellikle çok merak ettikleri video çekimlerinden biri de İstanbul-Ankara yolunda minibüs içerisinde yaptığımız çekimler :) Tüm bu çekimleri ve güzel anları birleştiren bir video hazırladım, yorumlarınızı bekliyorum :)

Sunday, October 26, 2008 9:40:03 PM (GTB Standard Time, UTC+02:00)  #    Comments [15]   Seminer  | 
 Saturday, October 25, 2008

Uzun bir süredir Silverlight anlatıyorum, 1.0 , 1.1 Alpha, 2.0 Beta 1, 2.0 Beta 2 derken RC ve RTW ile bugünlere kadar geldik. Bu süreçte onlarca seminer verdim, ücretsiz tam gün eğitimler yaptık ve bana hep sordunuz "Tam eğitim almak istersek nereye gideceğiz?" Bir türlü cevap veremedim size "Eğitim kurumlarına başvurun" dedim ve geçtim. Bu süreçte aslında birçok eğitim kurumu ile toplantı yaptım ve Silverlight eğitimleri açmaları için onları teşvik ettim. Bazıları sıcak baktı, bazıları soğuk, bazısı açtı ama duyurmadı :) her neyse.

Bundan bir ay önce BTAkademi ekibinden Sefer Algan ve Oğuz Yağmur ile bir toplantım oldu ve bu konuyu da konuştuk. Silverlight 2.0 eğitimi açmak istediklerini ve benim eğitmen olarak bulunup bulunamayacağımı sordular. Tabi ki cevabım "Evet" oldu. Maalesef hala sektörde Silverlight uzmanları kaynamıyor ve üzerimdeki sorumluluğun farkındayım. Bu çerçevede yeri geldiğinde ücretli eğitimleri de bilgiyi paylaşmanın bir yolu olarak görüyorum. Birazdan bahsedeceğim eğitim tam 36 saat sürüyor ve maalesef bu uzunluktaki eğitimleri ücretsiz yapmak pek mümkün olmuyor. Ben bugüne kadar en uzun bir konuyla ilgili 18 saatlik ücretsiz eğitim verdim.

Gelelim sadede...

Eğitim programı hazırlandı, ücreti BTAkademi belirledi ve duyurdu. Buradan detayları inceleyebilirsiniz. Umarım faydalı olur. Şimdi eminim bazılarınız aklında sorular belirecek;

Soru:Hocam sizin kendi şirketiniz yok muydu? Oradan eğitim verseniz?
Cevap: Eğitmenlik benim kişisel hobim. Şirket ise para kazandığım yer. Eğitmenliği birinci elden gelir kaynağı veya ticaret konusu olarak görmüyorum kendi adıma. O nedenle işi hali hazırda yapan kurumlarda yer alıp, bilgimi aktarıp çekilmeyi tercih ediyorum.

Soru:Hocam ücretsiz eğitimler falan bitti mi artık?
Cevap: Yooo, alakası yok. Bu konu ayrı, o konular ayrı. Ücretli eğitim sadece ayrı bir ihtiyaç. Birbirlerine karıştırmamak gerek. Olanağı olan var olmayan var. Ha bu eğitimden para kazanmayacak mıyım? Tabi ki kazanacağım :) herhalde BTAkademi hayrına eğitim vermemi siz de anlamsız bulurdunuz. Amaç "ticari" olunca her yönden öyle olmalı ve oluyor. Bu çerçevede belki kazandığımla biraz daha kilo alırım :P O kilolarla da ücretsizlere devam ederiz :)

Hepinize kolay gelsin.

Saturday, October 25, 2008 9:23:24 PM (GTB Standard Time, UTC+02:00)  #    Comments [6]   Silverlight 2.0  | 
 Friday, October 24, 2008

INETA Capital Hit'te ürettiğimiz içeriklerle ilgi daha birkaç post daha göndereceğim. Fotoğrafları vs hala topluyorum :) Şimdilik program içerisinde Panel'imizin video kaydını paylaşmak istiyorum. Aşağıdan hemen izlemeye başlayabilirsiniz.

Video'yu bilgisayarınıza indirmek isterseniz blogumun SeminerTV bölümüne geçebilirsiniz. ;) Normalde Panel'leri SeminerTV bölümüne koymuyordum fakat gelen talep yönünde artık katıldığım panelleri de bu bölüme koyacağım. Böylece eski INETA Summer Hit panelini de yine SeminerTV üzerinden bilgisayarınıza indirebilirsiniz.

Friday, October 24, 2008 2:04:20 PM (GTB Standard Time, UTC+02:00)  #    Comments [6]   Seminer  | 
 Thursday, October 23, 2008

Microsoft'un Photosynth gibi birçok yeni projesinin aslında ayrı araştırma ekiplerinin projeleri olduğunu ve sonradan ürünleştirildiğinden sanırım daha önce sizlere yazılarımda bahsetmiştim. Aslında bu çok normal bir süreç çünkü hiçbir büyük firma yeni ürün yaratacak "inovasyon"u gösteremiyor. Son cümlemin çok iddialı olduğunu biliyorum. Yazımın esas amacı bu olmadığı için istatistiklere girmeyeceğim fakat sizlere hızlı bir düşünme fırsatı vermek için Microsoft, Adobe, Google gibi büyük markaların son dönemlerde neler yaptıklarına bir göz atarken aslında hangi başka ürün ve kurumları satın aldıklarını da hatırlamanızı tavsiye ederim. Göreceksiniz ki çoğu büyük markaların yeni ürünleri aslında başka ufak firmalardan satın alınmış ürün ve hizmetlerdir. Bu konu çok uzun bir konu :) ama sonuç olarak Microsoft'un Labs, Research yapıları, Google'ın Google Labs'ı aslında bu sorunu çözmeyi hedefliyor.

MSDN Labs!

Kısa süre önce MSDN Labs duyuruldu. Şimdilik dört tane farklı proje var. Ben bunlardan özellikle "Small Basic" programlama dilinden bahsetmek istiyorum :)

Daha bir çocuğum yok, evli de değilim, hatta konu bu olunca "daha çok gencim" :) ama büyük ihtimal ile bir çocuğum olsa ilk günden eline şu yeni mini laptoplardan verir ve Visual Studio yüklerdim diye tahmin ediyorum :) İşe yarayabilirdi, ama günümüz Visual Basic'i artık çok da Basic değil! C#'dan hiç bahsetmek bile istemiyorum :) Oysa Basic'in zamanında yaratılırkenki misyonu aslında çok önemliydi ve Basic misyonunu yerine de getirdi. Bugün ise çocukların bu sektöre genç yaşta girebilmeleri, programlama dünyasının mantık cambazlıklarına "merhaba" diyebilmeleri için etrafımızda çok da basit programlama dilleri yok. Olanların ise sektördeki dillerle alakası yok. Oysa ben isterim ki ufacık yaşta öğrendiklerin programlama dilleri gelecekte de kullanabileceklerine bir altyapı sağlasın. Neyse konuyu çok uzatmayalım; karşınızda Small Basic.

Small Basic

.NET Framework üzerine kurulu altyapısı ile Small Basic'te toplam 15 adet keyword var. Hemen aşağıdaki adresten IDE'yi indirerek karıştırmaya başlayabilirsiniz

http://msdn.microsoft.com/tr-tr/devlabs/cc950524(en-us).aspx

Hemen Small Basic IDE'sini açarak Intellisense üzerinden komutları yakalayabilirsiniz. Her komutun detaylı açıklamaları da Intellisense içerisinde bulunuyor. Maalesef şimdilik her şey İngilizce :(

Small Basic IDE
Small Basic IDE

Yukarıda da gördüğünüz üzere hem arayüzün kendisi hem de Intellisense menüsü tamamen çocuklara hitap edecek şekilde düzenlenmiş durumda. Yazılan kod her zamanki gibi F5 ile çalıştırılabiliyor. Benim en sevdiğim ise entegre edilmiş Turtle (Kaplumbağa) kodları :) Turtle sınıfı altındaki metodlar ile ekranda bir kaplumbağa gezdirebiliyorsunuz ve gezdikçe arkasında bir çizgi bırakıyor. Amaç kaplumbağayı gezdirerek çizim yaptırmak :)

Kaplumbağa yolda...
Kaplumbağa yolda...

Small Basic gerçekten süper olmuş, bana çocukluk yıllarımı hatırlattı. Ah ah :) zamanında QBasic ile DOS'ta çırpınırdık şimdiki çocuklar çok şanslı! :) Yaşlandık mı nedir...

Thursday, October 23, 2008 5:11:44 PM (GTB Standard Time, UTC+02:00)  #    Comments [20]    | 
 Wednesday, October 22, 2008

Bugün neredeydim bilin bakalım? Google Internet Reklamcılığı seminerlerine gittim. Reklamcılık ile herhangi bir alakam yok fakat etraftan hep duyarım saçma sapan sitelerin ayda yüzlerce dolar kazandığı yolundaki dedikoduları ve tüm bunlar "SEO Optimizasyonu" şapkasına mal edilir sürekli. Haksızlar diyemem ama iki meta tagı ile yüzlerce dolar kazanma yalanına kanacak da değilim. Neyse, sonuçta nedir bu işin aslı, bakalım neler anlatacaklar diyerek gittim.

Bu ülkede etkinlik düzenlemesini bilen ajans yok mu?

Bugüne kadar onlarca Microsoft lansmanı, sunumu, konferansına katıldım. Hepsinde de eleştirdiğim noktalar oldu. Ama söz! bundan sonra Microsoft Türkiye'nin hiçbir aktivitesini eleştirmeyeceğim! Daha kötüsü varmış. Google Türkiye'nin Ritz Carlton'daki seminerleri için sitesinden kayıt olmanız gerekiyor demişlerdi, oysa gerekmiyormuş. Girişte kimse ne adımı ne soyadımı ne de başka bir şey sordu. Kartvizitimi aldılar ve kontrol bile etmediler. Yaka kartı vereceğiz dediler ve üzerinde büyük bir komedi patladı. Yaka kartı yerine üzerinde Google logosu olan sticker'lara keçeli kalemle girenlerin isimlerini kapıda bir yetkili duvarda yazdı!

  • Neden stickerlara isimler duvarda yazılıyor? masa yok mu? Ayarlayamadınız mı?
  • Neden sticker? Boyun askısı üretmeye değmez miydi?
  • Neden sadece katılımcıların isimleri yazıldı? Tamam tüm salonda bir Daron vardı ama birçok Mehmet vardı!

Bu ve bu gibi birçok şeye ÇOK şaşırdım. Aslında sonradan şaşırdığıma da şaşırdım :) Oysa uluslararası şirketlerin Türkiye ayaklarının çoğu zaman Uluslararası kurum kültür ve kalitesini yansıtamadığı gerçeğini çok gördüm.

Bitmedi başka yorumlarım da var organizasyonla ilgili; öğlen yemek verildi. Yemek güzel bir Ritz Carlton poşetinde dağıtıldı fakat katılımcılara yetmedi :) Her neyse bu detayı geçelim de o poşetin içindekileri kim planladı onu merak ediyorum ben.

  • Sandviç (Hoştur, gider)
  • Kola (Süper!)
  • Kek (Tatlı niyetine, bu da güzel)
  • Cips (Eh hadi google rahatlığı diyelim)
  • Domates / Peynir / Ceviz (Hönk! Ne alaka?)
  • Muz / Elma (İşte bu noktada koptum ben)

Şimdi bu nasıl bir yemek menüsüdür? Domates, peynir, ceviz, muz, cips, elma! Stok fazlası mallar mı toplandı yoksa menüyü bakkal amcada kalan mallara göre falan mı hazırladılar? Acaba Ritz Carlton'un böyle bir menüsü var mı? Yani kimse "dur kardeşim ne domates peyniri, sandviç veriyoruz ya!" demedi mi? Her şeye kıl olur bir durumum yok emin olun çok pozitif gittim ve negatif de çıkmadım ama bunun gibi şaşırdığım çok şey oldu. 500 kişilik salında 4 tane kafam kadar su şişesi tarzında aletle su ihtiyacını giderme konusuna değinmiyorum bile.

Şimdi bazılarınız diyeceksiniz "INETA Summer Hit!"de su yoktu :) Biz derneğiz! suya ihtiyacımız var :D Ben ticari kuruluşların aktiviteleri ile karşılaştırıyorum.

Elazığ tatilimde çektiğim bir foto, Google Elazığ şubesi olsa gerek :P
Elazığ tatilimde çektiğim bir foto, Google Elazığ şubesi olsa gerek :P

Gelelim içeriğe...

İçerikte sapıtma her aktivitede olur. Google'ınkinde de oldu. İlk 4 oturuma katıldım ve tamamen geyikti. Söylenene göre öğleden sonra toparlamışlar kaliteyi, umarım öyle olmuştur ben çoktan kaçmıştım. İçerikle ilgili en önemli sorun "verilmemesi gereken" bazı bilgilerin verilmesiydi. Örneğin XXXX Google Bıdı bıdı logosunu sitenizde kullanabilmeniz için 100.000$ AdWords satışı yapmanız gerektiği :) Doğal olarak bu o an için gereksiz olan bilgi bir anda insanlarda "eh çıkalım biz o zaman buradan" tepkisi yarattı. Pazarlamacı değilim de gördüğüm kadarıyla bu gibi bilgiler gerekmedikçe 500 kişilik salonlarda söylenmiyor :)

Genel yorumum o salondan birilerinin "yok abi artık google kullanmam ben ya" şeklinde çıktığı yönünde. Hatta bu bir yorum değil gerçek ama aynı şey ile Microsoft Türkiye organizasyonlarında da çokça karşılaştım. "Herkesi mutlu etmeye çalışmak" hatasına düşmemek gerek ama sanki birkaç ufak ayarla bu aktivitelerin başarısı daha arttırılabilir gibime geliyor.

İçerikle ilgili takıldığım diğer noktalardan biri de seminerde bir yenilik olarak custom search hödö hödönün anlatılmasıydı. Artık bir siteye yerleştirilen google arama motorunun istenilen diğer siteleri de arayabileceği, bu sitelerin listesinin de özelleştirilebileceği söylendi. Aklıma bir buçuk yıl önce yazdığım bir makale geldi. Hatta aynı makale bir de Google logosu dışında arama motoru sisteminin tamamen özelleştirilebileceğini söylediklerinde aklıma geldi :) Live.Com'da her ikisi de yıllardır yapılıyor hatta isterseniz Live.Com logosu vs kullanmadan da ilerleyebiliyorsunuz. Ah ahh...

Daha ilginci Google Maps'in açık kaynak kodlu olduğu söylendi! Nesi açık kaynak ben onu anlamadım? JavaScript ve DHTML kodları mı? Zaten onları nasıl kapatacaksınız ki? Yoksa sunucu tarafındaki yazılımı mı açık kaynak? Yani biz Google Maps'in sunucu tarafındaki altyapısının kodunu inceleyebiliyor muyuz? Yoksa istemcideki "istemci yazılımını" kast ederek bizi "Google Maps açık kaynak kodludur" şeklinde keklemeye mi çalıştılar çok net anlayamadım :) Bilgisi olan varsa yorum yazarak beni düzeltsin lütfen.

Bir de aktiviteye katılanlar hatırlayacaktır bir sunumda slayt içerisinde video vardı ve oynamadı :) Sunumu Powerpoint ile hazırlar ama Windows değil de anti-MS Mac'te göstereyim diye linkli video dosyasını taşımayı unutursanız böyle olur. Dikkat etmek gerek bu gibi konulara. Tabi slaytların tasarım rezaletine ve 10 punto 80 sayfa yazı içeren slaytları hazırlayanların nasıl olup da konuşmacı olarak yüzlerce kişinin karşısına en ufak bir sunum eğitimi almadan çıkarıldığına hiç değinmeyeceğim. Ama yine diyorum ben öğleden sonra yoktum en son Hatice adında bir bayanın sunumunu izledim (yemekten sonraki son sunum) ki kendisi kaliteyi yükseltmiş olmasa herhalde bu yazım daha ağır olurdu.

MS TR etkinliklerindeki eleştirilerime duacıyım artık. En fazla konuşmacıların hitap becerisi veya bilgi birikimini eleştiriyordum, burada neler neler çıktı karşıma.

Sonuç

Optimizasyon vs geyiktir, esas para kullanıcıları kandırmakta :) Reklam olduğunu anlamayıp bolca tıklasınlar yeter ;) Eh bunu nasıl sağlayacağınız da meslek sırrı optimizasyonlar sınıfına giriyor. Tamam tamam kabul ediyorum bir sitenin teknik olarak da aranabilir olması gerek ama esas haksız rekabet diğer alanda yürüyor.

Sevgiler...

Wednesday, October 22, 2008 7:16:25 PM (GTB Standard Time, UTC+02:00)  #    Comments [29]   Dertli Kerem  | 
 Tuesday, October 21, 2008

.NET 3.5 SP1 ile beraber gelen Dynamic Data Web Site yapısı ile beraber doğrudan sadece veri üzerinde çalışan web uygulamaları yazmanın gerçekten kolaylaştığını itiraf edebiliriz. Fakat her yeni araç gibi Dynamic Data ile beraber de istediklerimizi yapabilmek için kendine özgü özelleştirme kurallarını bilmemiz gerek. Bu yazıda elimizde hazır bir Dynamic Data Web Site olacak ve bu web sitesinde gösterilen veritabanındaki bazı tablolardaki bazı sütunların gösterim esnasındaki özelleştirmelerine değineceğiz. Cevaplayacağımız sorulardan bazıları şunlar olacak;

  • Belirli bir tablonun sadece bir sütununun görünmemesini nasıl sağlarım?
  • İstediğim bir sütunun istediğim değerleri almasını nasıl sağlarım?

Yazımızda kullanacağımız örnek siteyi yaratmak için buradaki yazıyı inceleyebilirsiniz.

MetaData üzerinden ayarlamalar...

Dynamic Data yapısına baktığımızda olabildiğince her şeyin otomatik ilerlediğini görüyoruz. Örneğin bir tablonun içerisindeki tüm sütunlar otomatik olarak söz konusu tablo ile beraber tüm sayfalarda düzenlenebilir şekilde gözükmeye başlıyor. Sütunlarla ilgili tek tek ayar yapmanın tek yolu söz konusu sütunlara ek MetaData bilgileri vermek. Peki bizim sütunlarımızı kodumuzla kim tanımlıyor?

Biz projemizde LINQ2SQL kullanarak ilerlediğimiz için veritabanındaki her bir nesneyi tanımlayan objeler LINQ'e ait DBML'in arkasında tanımlanmış durumda. Bir DBML dosyasının arkasına baktığınızda designer.vb veya designer.cs uzantılı dosyalar görebilirsiniz. Bu dosyalar içerisinde veritabanındaki tüm nesnelerin birer kopyası .NET nesneleri olarak yaratılmıştır.

[VB]

<Table(Name:="dbo.Urunler")>  _

Partial Public Class Urunler

    Implements System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged

[C#]

[Table(Name="dbo.Urunler")]

public partial class Urunler : INotifyPropertyChanging, INotifyPropertyChanged

{

Yukarıda gördüğünüz şekilde başlayan Urunler adındaki Class DBML dosyasının arkasında duruyor ve bizim her bir ürünümüzü tanımlıyor. Maalesef bu designer dosyalarında değişiklik yapamıyoruz. Aslında değişiklik yapabilirsiniz fakat DBML dosyasında Visual Studio arayüzündeki tasarım araçları ile yaptığınız her işlem bu dosyaların sistem tarafından tekrar yaratılmasına neden olacağı için kullanıcı tarafından yapılan tüm kod değişiklikleri kaybolacaktır. Peki bu durumu nasıl çözeceğiz? Dikkat ettiyseniz tüm bu sınıflar Partial olarak tanımlanmıştır yani bir başka bir dosyada tekrar Partial birer sınıf yaratarak işlemlerimize devam edebiliriz. Bu durumda buyurun yeni bir VB/CS dosyası oluşturalım ve Partial olarak aynı sınıftan bir adet daha yaratalım.

[VB]

<ComponentModel.DataAnnotations.MetadataType(GetType(UrunlerMeta))> _

Partial Public Class Urunler

 

End Class

[C#]

[System.ComponentModel.DataAnnotations.MetadataType(typeof(UrunlerMeta))]

public partial class Urunler

{

 

}

Yukarıdaki koda baktığınızda özellikle en üstteki MedadataType işaretleri dikkatinizi çekecektir. Aslında bu da bir MetaData fakat maalesef bu şekilde Partial sınıflara doğrudan MetaData veremiyoruz. O nedenle başka bir sınıf yaratarak MetaData'ları orada tutacağız ve o sınıftan MedaData'ları bu tarafa aktaracağız. Kodumuz içerisinde UrunlerMeta olarak geçen obje aslında başka bir sınıfın adı.

[VB]

Public Class UrunlerMeta

 

    Private _Fiyati As Object

    <ComponentModel.DataAnnotations.Range(10, 20, errormessage:="Hata!")> _

    Public Property Fiyati() As Object

        Get

            Return _Fiyati

        End Get

        Set(ByVal value As Object)

            _Fiyati = value

        End Set

    End Property

 

End Class

[C#]

public class UrunlerMeta

{

    [System.ComponentModel.DataAnnotations.Range(10, 20, ErrorMessage = "Hata!")]

    public object Fiyati { get; set; }

}

UrunlerMeta sınıfı içerisinde sadece Fiyati adında bir Property var. Aslında ana Urunler sınıfındaki tüm Property'leri burada da tanımlayarak kullanabilirdik fakat şimdilik bize Fiyati Property'si yeterli. ComponentModel.DataAnnotations altından Range sınıfını kullanarak Fiyati değerinin 10 ile 20 arasında olmak zorunda olduğunu ve bu durumun sağlanmaması halinde de hata olarak "Hata!" yazısının gösterilmesi gerektiğini belirtiyoruz. Gelin bu kodun bir de web sitesindeki yansımasına göz atalım.

Range sınıfı ile yaptığımız ayarlamalar arayüzde kendini gösteriyor.
Range sınıfı ile yaptığımız ayarlamalar arayüzde kendini gösteriyor.

Başka neler yapabiliriz?

MetaData'lar üzerinden başka neler yapılabileceği ile ilgili çok sayıda farklı senaryo mevcut fakat en basit örnekleri inceleyebilmek için kabaca ComponentModel.DataAnnotations sınıfına göz atmak yeterli olacaktır. Örneğin aşağıdaki gibi bir kod istediğiniz bir kolonun web sitesinde gösterilmemesini sağlayabilir.

[VB]

<ComponentModel.DataAnnotations.ScaffoldColumn(False)> _

[C#]

[System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]

Peki ya diğer seçenekler? Gelin hızlı bir tur atalım.

DisplayColumn

Bu özellik toplam en fazla üç parametre alabilir. Amacı tablolar arası ilişkilendirmelerde kullanıcının gördüğü metinleri değiştirmektir. Örneğin bizim projemizde ürünlere bağlı olan kategorilerin adları otomatik olarak her üründe gösteriliyor. Sistem aslında arka planda Kategoriler tablosunda ID(PK) kolonundan sonra karşılaştığı ilk String kolonu alarak göstermeye göre ayarlı. Oysa bazı durumlar FK'in bağlı olduğu tablodan alınması gereken ve gösterilecek olan metin çok daha ileride farklı bir sütunda olabilir. İşte DisplayColumn bunu ayarlıyor ve bir FK durumunda ana tablodan hangi sütunun bu üründe gösterilmesi gerektiğine karar veriyor. Bunun haricinde aldığı iki diğer parametrenin ilki hangi kolon üzerinden Sorting yapılabileceği ve üçüncü parametre ise Sorting işleminin ilk açılışında hangi yönde yapılacağı verisini taşıyor.

RegularExpression

Kendisine ilk parametre olarak verilen RegEx desenini hedef kolona test eden ve uyuşmaması durumunda da ikinci parametre olarak verilen hata mesajının gösterilmesini sağlayan bir Validation sisteminin entegrasyonuna yönelik olarak kullanılabilir.

Required

Sadece tek bir parametresi vardır; eşleştirildiği sütun için veri girilmez ise gösterilmesi gereken hata mesajını String olarak alır.

ScaffoldTable

Tablo sınıflarına doğrudan verilebilen bu MetaData ile bir tablonun web sitesi görselliğinde gösterilip gösterilmeyeceğini belirler.

StringLength

Bir sütuna girilebilecek maksimum metin uzunluğu ilk parametresi olarak alır. İkinci parametresinde ise söz konusu uzunluk aşıldığında gösterilecek olan hata mesajını saklar.

Sonuç

Yazı boyunda Annotation'lar içerisinde atladığım bazı seçenekler oldu. Bu seçenekleri ileriki yazılarda daha detaylı olarak incelememiz gerektiği için şimdilik yüzeysel olarak geçmek istemedim.

Hepinize kolay gelsin.

Tuesday, October 21, 2008 2:36:26 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   ASP.NET 3.5 | LINQ  | 
 Monday, October 20, 2008

Hafta sonunu Ankara'da geçirdik. Neden mi? INETA Capital Hit zamanıydı! Atladık INETA minibüsümüze :) yollara düştük. Maceralarımızla ilgili videolar ve fotoğraflar çok yakında bu blogda :)

İki kocaman gün boyunca dopdolu bir programla Çankaya Üniversitesi'nde iki yüz elli kişilik bir ekip olarak yattık kalktık diyebilirim. Yine her zamanki gibi benim için muhteşem zevkliydi.

Pazar akşamı saat yedide Capital Hit'i sonlandırdık.
Pazar akşamı saat yedide Capital Hit'i sonlandırdık.

Aktiviteye katılan tüm konuşmacı dostlarıma binlerce teşekkür. Ayrıca Çankaya Üniversitesi Bilişim Kulübü ve sevgili MSP, Çağrı Erdoğan'a da çok teşekkürler. Bir organizasyonda ancak bu kadar başarılı bir misafirperverlik sergilenebilirdi.

Tabi ki her şey bu kadarla bitmiyor! Elimde birçok fotoğraf, minibüs yolculuğumuzdan videolar ve panel kaydımız var. Hepsini büyük bir hızla hazırlamaya çalışıyorum. En kısa zamanda sizlerle buradan paylaşacağım.

Şimdilik aşağıdaki sunumlarla idare edelim :)

AdoNet Data Services / Burak Selim Şenyurt - 20102008_1.pptx (1,01 MB)
LINQ / Uğur Umutluoğlu - 20102008_2.pptx (750,29 KB)
WCF / Burak Selim Şenyurt - 20102008_3.pptx (460,14 KB)

Not: Bu sefer ben hiç sunum kullanmadım, doğrudan demolarla ilerledim. O nedenle sunum paylaşamıyorum.

Monday, October 20, 2008 6:24:54 PM (GTB Standard Time, UTC+02:00)  #    Comments [9]   .NET Framework 3.5 | ASP.NET 3.5 | Expression Blend | Haberler | IIS 7.0 | LINQ | Seminer | Silverlight 2.0 | WCF | WPF  | 
 Sunday, October 19, 2008

Photoshop hayatımızın o kadar göbeğine oturmuş durumda ki dilimize bir fiil olarak girdiğini bile söyleyebiliriz, "photoşoplanmıştır o!" gibi deyimler pek de yabancı değil :) Bu yazıda size Photoshop'tan DeepZoom projeleri Export etmenizi sağlayacak bir Plug-In'den bahsedeceğim.

İlk olarak aşağıdaki adresten "HD View Utilities" paketini bilgisayarınıza yüklemelisiniz. Bu paket içerisinde Photoshop Plug-In'i de bulunuyor.

http://research.microsoft.com/research/downloads/details/345a52c3-fe44-4045-94b4-4b26a93a907c/details.aspx

Yükleme işlemini tamamladıktan sonra yüklemeyi yaptığınız konumda HDView.8be adında bir dosya bulacaksınız. Bu dosya doğrudan bir Photoshop Plug-In dosyasıdır. Dosyayı alarak Photoshop'un bilgisayarınızda kurulu olduğu klasörde Plug-Ins\Import-Export konumuna kopyalamanız gerek. Tüm bunları tamamladığınızda artık herhangi bir dosya Photoshop içerisinde açıkken doğrudan File / Export menüsünde bulabilirsiniz.

Photoshop içerisinden Silverlight 2.0 DeepZoom çıktısı!
Photoshop içerisinden Silverlight 2.0 DeepZoom çıktısı!

Aşağıda Elazığ gezimden Palu dağında çekmiş olduğum panoramik fotoğrafı inceleyebilirsiniz :) Fotoğrafın bilgisayarımdaki kayıtlı hali 45MB.

Sunday, October 19, 2008 3:42:19 PM (GTB Standard Time, UTC+02:00)  #    Comments [6]   Photoshop | Silverlight 2.0  | 
 Saturday, October 18, 2008

HD Photo mantığı aslında adından da az çok anlaşılabileceği üzere yüksek çözünürlüklü (High Definition) fotoğraf yayını ile ilgili bir kavram. Daha önceki yazılarımdan birinde sizlere Image Composition Editor'dan bahsetmiştim. Ücretsiz bir araç olarak hem DeepZoom projeleri hem de 360 derece HD View çıktıları alabiliyordu. Normalde HD View'ın istemci tarafında çalışabilmesi için ayrı bir Plug-In kullanılması gerekirken artık ekip bu işlevselliği Silverlight tarafına taşımış ve DeepZoom ile 360 derece görüntü sistemini birleştirmiş. Tek yapmanız artık Image Composition Editor içerisinde DeepZoom seçeneğini seçerek Export almak.

Buyurun size 360 derecelik bir manzara...

Saturday, October 18, 2008 2:51:57 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Silverlight 2.0  | 
 Friday, October 17, 2008

Bir süre önce ben de feedburner.com üyesi olarak blogumun RSS'lerini FeedBurner üzerinden yayınlamaya başladım. Buna ek olarak RSS kullanmak istemeyenler veya sevmeyenler için FeedBurner'ın bir de mail atma hizmeti var. Her gün benim bloga eklenmiş yazılar varsa onları size mail olarak gönderiyor. Eğer bu şekilde blogumu takip etmek size daha uygun geliyorsa aşağıdaki linkten kayıt olarak mail trafiğini başlatabilirsiniz ;)

http://www.feedburner.com/fb/a/emailverifySubmit?feedId=1981693&loc=en_US

Friday, October 17, 2008 7:31:55 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]    | 
 Thursday, October 16, 2008

Şu FaceBook'dan vaz geçemedik gitti bir türlü. Bir çılgınlık aldı başını gidiyor. Bir PostBack ile 100 event invitation gönderme sınırı olup son 40 denememim hiçbirinde bunu beceremeyecek kadar zayıf altyapısı ile her gün beni daha da şaşırtan böyle bir programcılık rezaleti hala dimdik ayakta. Ben de tabi bu çılgınlıktan payımı aldım.

İlk olarak birileri nasıl olduysa beni evlendirmeye karar verdi ve sonrasında "Daron Yöndem'le Evlenmek/Evlenmesini İsteyenler" grubu kuruldu. Utanmadan :) beni de gruba davet ettiler! Tabi ki kabul etmedim. Birincisi grubun adı yanlış :) kimin evlenmek isteyip kimin evlenmemi istediği belli değil, ikincisi grubun üyelerinin %99'u ERKEK! İmdat!

Sonra da bana amigo muamelesi yapmaya çalıştığını tahmin ettiğim "Daron Yöndem buraya yumruk havaya" grubu açıldı.

Daha mı? Daron Yöndem Fan Club açtılar! Sonra da beni FaceBook'da Celebrity olarak tanımladılar!

Şimdi bana LinkedIn ve FriendFeed gibi yerlerden davetiyeler atanlara sesleniyorum :) Oralara da geleyim şebeğe çevirin dimi adamı? Zaten hala neden benim avatarımın yanında hep "Kilo Verme Hapları"nın reklamları çıkıyor anlamış değilim! Nedir bu arkadaşım ya! :)

Thursday, October 16, 2008 7:19:27 PM (GTB Standard Time, UTC+02:00)  #    Comments [16]   Dertli Kerem  | 
 Wednesday, October 15, 2008

Bugün sizlerle yeni bir açık kaynak kodlu Silverlight 2.0 uygulamamı paylaşacağım. Hatırlarsanız bundan aylar önce Silverlight 1.0 ile bir Twitter Widget hazırlamış ve sizlerle kaynak kodlarını paylaşmıştım. Şimdi de 2.0 ile yeni bir Widget hazırladım. Bu sefer Widget'ın TwitXR desteği gibi ilginç özellikleri var

Bir Widget hikayesi...

Silverlight 2.0 ile geliştirme yapmanın 1.0'a kıyasla çok sayıda avantajı var fakat unutmayalım ki artık .NET tarafındayız ve JavaScript ile olduğu kadar low level kod yazmıyoruz. Ne demek istediğimi makale boyunca daha net anlayacağınızdan eminim. Peki size neler anlatacağım?

Uygulamanın içindeki kodların açıklamalarını zaten kodlar içerisindeki yorum satırlarında bulabilirsiniz. Yorum satırlarını İngilizce yazdım çünkü uygulamayı yurt dışı ile de paylaşacağım. Önemli olan ve benim özellikle değinmek istediğim noktalar bir Widget hazırlarken karşılaştığım duruma özel sorunlarla ilgili. Gelin daha fazla konuşmak yerine sorunlara el atalım.

Twitter API saçmalığı!

Twitter'ın çok güzel bir XML API yapısı var. Sorunlardan ilki bu API için ister Flash ister Silverlight hiç fark etmez ClientAccessPolicy dosyası konmamış, yani Cross-Domain-Request yasak! Durum böyle olunca sunucu tarafında bir proxy oluşturarak veriyi kendi sunucunuzaalıp kendi Widget'ınıza aktarmanız gerekiyor, ama bunu da yapamıyoruz çünkü şöyle bir saçmalık mevcut; istemci başına bir saatte 70 request sınırı var. Eeee? Tüm requestleri benim Web Server'ım yapacak sonuçta tüm ziyaretçiler için, 70 kesinlikle kabul edilebilir bir sınır değil. Büyük ihtimal ile Windows uygulamaları falan düşünülmüş.

Sonuç olarak Silverlight 1.0 Widget'da kullandığımız Remote Script Injection ile Cross-Domain-Reqest taktiğini Silverlight 2.0 da da kullanmamız gerek. Dinamik olarak sayfaya bir script tagı ekleyip twitter sitesinden JavaScript alıp sitemizde çalıştırıyorduk. Parametre olarak da bizim istediğimiz veriler geliyordu. İşte sorular;

Silverlight 2.0 ile dinamik Script tagları sayfaya nasıl eklenir?

        'Insert our dynamic Script Tag to get Cross Domain Data

        Dim MyDoc As HtmlDocument = HtmlPage.Document

        Dim ScriptTag = MyDoc.CreateElement("script")

        ScriptTag.SetAttribute("type", "text/javascript")

        ScriptTag.SetAttribute("src", "http://twitter.com/statuses/user_timeline/" & InitParams("twitterid") & ".json?callback=TwitterIncData&count=" & InitParams("count"))

        MyDoc.Body.AppendChild(ScriptTag)

Yukarıdaki kod ile rahatlıkla dinamik olarak bir Script tagı yaratıp özelliklerini de ayarlayıp içerisinde bulunduğumuz sayfanın Body'sine ekleyebiliyoruz. Böylece uzaktaki dosya çağrılacaktır. Twitter adresinin içindeki parametrelerin konumuzla şimdilik alakası yok. Ama bu adres üzerinden gönderdiğimiz callback parametresi Twitter'dan data gelince sayfamızda çalıştırılacak olan JavaScript'in ta kendisi. Peki bu durumda data gelince çağrılan JavaScript'ten bizim Silverlight 2.0'ın nasıl haberi olacak?

JavaScript'ten Silverlight 2.0 fonksiyonları nasıl çağrılır?

Buyurun makalemi okuyun : http://daron.yondem.com/tr/PermaLink.aspx?guid=a1426eb0-7120-4a66-9d5c-de5027fd59ed

Şimdi veri geldi elimize ama gelen veri JSON! Bunu nasıl olacak da anlaşılabilir bir hale çevireceğiz ve .NET nesneleri şeklinde kullanabileceğiz?

JSON verisi Silverlight 2.0'a nasıl alınır?

Buyurun bir makale daha: http://daron.yondem.com/tr/PermaLink.aspx?guid=457fbb28-892e-4a37-b7d3-cb297d97020b

Ama ben yukarıdaki makalede anlatılanı yapmadım, JSON'dan çekmek istediğim veri belli olduğu için ve twitter'ın JSON formatı basit olduğu için doğrudan aşağıdaki kod ile gelen her JavaScript nesnesine ScriptObject muamelesi yaptım.

        For x As Integer = 0 To CInt(InitParams("count")) - 1

            AllData.Add(New TwitPost(JSON.GetProperty(x).GetProperty("text").ToString, JSON.GetProperty(x).GetProperty("created_at").ToString, JSON.GetProperty(x).GetProperty("id").ToString))

        Next

Yukarıda JSON değişkeninin içerisinde doğrudan JavaScript tarafından gelen JSON objesi bulunuyor. GetProperty metodu ile herhangi bir diziden istediğimiz öğeyi ve özelliklerini tek tek alabiliyorum.

Bir sonraki sorunumuz hangi Twitter hesabından veri çekeceğimiz Widget'ı kullananların nasıl karar verebileceği. Bunun için Silverlight 2.0'ın sayfaya yerleştirildiği Object taglarının parametrelerini kullanacağız.

Parametreli Silverlight 2.0 dosyaları kullanımı nasıl olur?

Buyurun size bir makale : http://daron.yondem.com/tr/PermaLink.aspx?guid=4834596e-b5ec-450f-8e3c-cfba929d958e

Twitter'dan data alma işleminin Widget'ın bulunduğu sayfa tamamen yüklendikten sonra başlasın istiyoruz. Bun durum data yüklendikten sonra DOM'a ulaşıyor olmamızdan kaynaklanıyor, eğer sayfa tam yüklenmemişse daha DOM listeleri sabitlenmemiş olabilir.

HTML / DOM eventlarını Silverlight 2.0 ile nasıl yakalarım?

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim MyDoc As HtmlDocument = HtmlPage.Document

        HtmlPage.Window.AttachEvent("onload", AddressOf DocLoaded)

    End Sub

 

    Private Sub DocLoaded(ByVal sender As Object, ByVal e As EventArgs)

      

    End Sub

Yukarıdaki kod ile yaratmış olduğunuz bir event-handlerı nasıl sayfanın eventların veya bulduğunuz herhangi bir HTML nesnesinin eventlarına ekleyebileceğinizi görebilirsiniz. Kullanım şekli epey basit.

Bir sonraki adımda bir TextBlock içerisine farklı formatlarda yazı eklemek istiyoruz. Bunda zor ne var? diyebilirsiniz :) Ama bir TextBlock'un Text özelliğine baktığınızda String tipinde olduğunu görüyorsunuz. Peki buna nasıl bir formatlama bilgisi aktarabiliriz ki? Aktaramayız :) Aslında TextBlock'un bir de Inlines diye bir dizisi var. Bunun içerisinde satır içi Item'lar saklanıyor. Eğer Inlines ile ilgili bir ayarlama yapılmamışsa ve doğrudan Text özelliği set edilmiş ise arkaplanda otomatik olarak bir Inline Item yaratılarak bu diziye ekleniyor. Tüm bunlar programatik olarak da yapılabilir.

Bir TextBlock'un içindeki belirli bir metnin rengi programatik olarak nasıl değiştirilir?

            Dim Span As New Documents.Run

            Span.Text = AllText.Substring(0, AllText.IndexOf(FoundURLs.Item(0).Value))

            Span.Foreground = CType(App.Current.Resources("PostTextForeGround"), SolidColorBrush)

            Current.Inlines.Item(0) = Span

            Span = New Documents.Run

            Span.Text = FoundURLs.Item(0).Value

            Span.Foreground = CType(App.Current.Resources("PostTextLinkForeGround"), SolidColorBrush)

 

            Span.TextDecorations = TextDecorations.Underline

            Current.Inlines.Add(Span)

            Span = New Documents.Run

            Span.Text = AllText.Substring(AllText.IndexOf(FoundURLs.Item(0).Value) + FoundURLs.Item(0).Value.Length, AllText.Length - (AllText.IndexOf(FoundURLs.Item(0).Value) + FoundURLs.Item(0).Value.Length))

            Span.Foreground = CType(App.Current.Resources("PostTextForeGround"), SolidColorBrush)

            Current.Inlines.Add(Span)

Yukarıdaki kod içerisinde Current değişkeni aslında bir TextBlock. Bu TextBlock içerisinde URL'i alıp URL'den öncesini ayrı bir Run olarak, URL'i ayrı bir Run olarak, kalanı da ayrı bir Run olarak TextBlock'un Inlines dizisine ekliyoruz. Böylece her bir Run için görsel olarak farklı ayarlar yapabiliyoruz.

Yazımın en başında TwitXR desteği derken ne demek istediğimi biraz anlatıyım. Twitter ile TwitXR beraber çalışan sitelerdir aslında. TwitXR üzerine yolladığınız bir resim ve yazı otomatik olarak Twitter'a da aktarılır. Bizim Widget Twitter'dan Post'ları alırken kontrol edecek eğer o Post TwitXR'dan gelmişse uygun fotoğrafı da bularak gösterecek. Tüm bu hikayede benim istediğim nokta TwitXR'dan alınan resim istemciye yüklenirken yüklemenin durumundan haberdar olmaktı. Yani resmi istedim ama tam olarak yüklendi mi yoksa indiriliyor mu?

Remote Image yüklerken Progress göstermek!

Başından beridir Remote-Request'e izin verilmiyor ve Policy dosyaları yok diyoruz! Bu durumda benim normal bir WebClient sınıfı ile resmi indirmem ve sonra gelen Stream'i Image nesnesine bağlayıp sahneye koyma şansım yok. Mecburen Image'ı doğrudan Image nesnesine bağlamak zorundayım, ancak bu şekilde remote resim alabiliyorum. Ama bunu yaparken de zaten Imaging.BitmapImage sınıfını kullanmak zorundayım ve bu sınıfın kendine özel bir DownloadProgress'i var :)

 WithEvents PhotoDownload As New Imaging.BitmapImage

 

    'The Photo for the PhotoFrame has been downloaded.

    Private Sub PhotoDownload_DownloadProgress(ByVal sender As Object, ByVal e As System.Windows.Media.Imaging.DownloadProgressEventArgs) Handles PhotoDownload.DownloadProgress

        If e.Progress = 100 Then

            GetBig(MousePos.Y)

        End If

    End Sub

 

    'Play the anim when the mouse is on

    Private Sub Clickable_MouseEnter(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)

            PhotoDownload.UriSource = New Uri(MyPhoto, UriKind.Absolute)

            Photo.Source = PhotoDownload

    End Sub

Yukarıdaki kod içerisinde PhotoDownload adındaki BitmapImage'e fotoğrafın URL'ini veriyorum ve sonra da Photo adında Image UIElement nesneme Source olarak veriyorum. Böylece Silverlight resmi BitmapImage ile indirerek Image nesnesine bağlayıp göstermeye çalışıyor. Bu esnada BitmapImage'ın DownloadProgress'i çalışıyor. İlginç bir şekilde bu Progress event'ı içerisindeki Progress özelliği 1 ile 0 arasında olması gerekirken ya 0 ya da 100 döndürüyor. Normalde 0 = indirilemedi ve 1 = indirildi anlamına gelmeliydi. Sanırım bu bir BUG :) Her neyse bir işimizi şimdilik halletik. Unutmayın buradaki Progress WebClient'taki biri Double değil, Integer. Yani aslında bir Progress değil de Status değeri veriyor.

Şeffaf uygulama ve Overlay Sorunu

Aslında uygulama fonunu şeffaf yapmak çok kolay. Buyurun makalesi : http://daron.yondem.com/tr/PermaLink.aspx?guid=b334e195-feb7-4411-a77d-b6f07d482068

Esas sorun ben şeffaf olan yerlerin sadece şeffaf gözükmesini değil aynı anda o şeffaflığın arkasındaki HTML'in de kullanılabilir olmasını istiyorum. İşte bu olmuyor! Hedefim Widget içerisinde herhangi bir Post'un fare ile üzerine gelince yana doğru sayfanın üzerine taşacak şekilde uygulamanın genişlemesi ve orada da postun fotosunun gözükmesi. Tabi tüm uygulama gelişmeyecek sadece fotoğrafın gözükeceği bir kısım açılacak. Şeffaf fon kullanıldığında görsel olarak bir sorun yok gibi gözükse de bir bakıyorsunuz ki şeffaf olmasına rağmen uygulama alanınız fotoğrafın gösterileceği yerleri de kapsadığı yani sayfaya taştığı için o kısımlardaki HTML kontrolleri çalışmıyor. Bu konu maalesef Flash'ta daha iyi çözülmüş durumda, Flash'ta şeffaf olan yerler gerçekten şeffaf :(

Peki nasıl çözeriz, dinamik olarak Silverlight uygulamasının sayfadaki kapladığı alanı yine kodlarımız ile düzenlememiz gerek. Silverlight'ın OBJECT taglarına bir ID değeri vererek bunun üzerinden OBJECT'in genişliğini değiştirebiliriz.

        HtmlPage.Document.GetElementById("TwitterSLWidget").SetAttribute("width", "360px")

Bu kod ile kullandığımız OBJECT tagları aşağıdaki gibi.

                <object style="position:absolute; z-index: 2;" id="TwitterSLWidget" data="data:application/x-silverlight-2,"

                    type="application/x-silverlight-2">

                    <param name="source" value="ClientBin/TwitterWidget.xap" />

                    <param name="initParams" value="twitterid=daronyondem,count=10,twitxrid=daronyondem" />

                    <param name="onerror" value="onSilverlightError" />

                    <param name="background" value="Transparent" />

                    <param name="pluginbackground" value="Transparent" />

                    <param name="windowless" value="true" />

                    <param name="background" value="white" />

                    <param name="minRuntimeVersion" value="2.0.31005.0" />

                    <param name="autoUpgrade" value="true" />

                    <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

                        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"

                            style="border-style: none" />

                    </a>

                </object>

Widget'ı nasıl kullanırız?

Birazdan kaynak kodları ile beraber Widget'ı sizinle paylaşacağım. Ama onun öncesinde hemen Widget'ı nasıl kullanırız ona bakalım.

            <div id="TwitterSLWidgetHost">

                <object style="position:absolute; z-index: 2;" id="TwitterSLWidget" data="data:application/x-silverlight-2,"

                    type="application/x-silverlight-2">

                    <param name="source" value="ClientBin/TwitterWidget.xap" />

                    <param name="initParams" value="twitterid=daronyondem,count=10,twitxrid=daronyondem" />

                    <param name="onerror" value="onSilverlightError" />

                    <param name="background" value="Transparent" />

                    <param name="pluginbackground" value="Transparent" />

                    <param name="windowless" value="true" />

                    <param name="background" value="white" />

                    <param name="minRuntimeVersion" value="2.0.31005.0" />

                    <param name="autoUpgrade" value="true" />

                    <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

                        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"

                            style="border-style: none" />

                    </a>

                </object></div>

Yukarıdaki HTML kodunu sayfanıza yerleştirmeniz gerekiyor. Özellikle koyu olan yerlere dikkat. daronyondem yerine kendi Twitter ve TwitXT hesaplarınızın adlarını yazmanız gerek. count kısmına da koç Post gözüksün istiyorsanız onu yazabilirsiniz. OBJECT ve DIV taglarının ID'leri çok önemli. Bu ID'ler kodlarda kullanılıyor, eğer değiştirirseniz kodları da tekrar düzenleyip XAP dosyasını Compile etmeniz gerekecektir.

       function TwitterIncData(object)

        {

        document.getElementById("TwitterSLWidget").Content.Page.IncData(object);

        }

Son olarak yukarıdaki kodu da sayfanızda uygun bir JavaScript dosyasına veya tagları arasında koymanız ve XAP dosyasını sunucuya kopyalamanız yeterli olacaktır.

Kaynak Kodlar

Tüm projenin kaynak kodlarını aşağıdaki adresten indirebilirsiniz. Proje epey karışık oldu, özellikle Remote Script Injection kullandığımız için Cross-Browser uyumluluğu konusunda sıkıntılar var. Diğer yandan Overlay konusunda da farklı tarayıcılarda sorunlar var. O nedenle şimdilik ben ancak IE 7 desteği sunabiliyorum, uğraşacak pek zaman olmadı. Eğer siz uygulamayı diğer tarayıcıları da destekleyecek şekilde modifiye ederseniz beni haberdar etmeniz yeterli. Böylece mini bir açık kaynak projesi olmuş olur.

Makaledeki tüm kodlar VB :) çünkü uygulamadan kesip yapıştırdım. Uygulamayı da malum VB ile yazdım :) C#'cılara selamlar :)

Silverlight 2.0 Twitter / TwitXR Widget
Kaynak Kodlar ve Proje - 15102008_1.rar (558,89 KB)

Hepinize kolay gelsin.

Wednesday, October 15, 2008 10:28:42 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Silverlight 2.0  | 
 Tuesday, October 14, 2008

Silverlight 2.0 sonunda yayınlandı. Bana çook uzun gelen bu bekleyişin sonunda hem bazı şeyleri tekrar ederek hem de SL 2.0 ile ilgili yeni bilgiler vererek bu dünyaya giriş yolunda başlangıç noktasında olanlar için bir rehber hazırlamaya karar verdim. Buyurun beraber ilerleyelim.

Silverlight 2.0 Runtime

Silverlight uygulamalarının istemci tarafında yani tarayıcı içerisinde çalışabilmesi için sistemde Silverlight 2.0 RunTime'ın yüklü olması gerekiyor. Bu paket şu anda 4MB büyüklüğünde ve otomatik olarak RunTime'ı yükleyecek mekanizmalar zaten Silverlight projelerine dahil ediliyor. Bu RunTime şu anda tüm tarayıcılarda çalışıyor ve Windows, Mac sürümleri mevcut. Windows Mobile, Linux ve Symbian konusunda çalışmalar devam ediyor.

Silverlight 'ın çalışabilmesi için sunucu veya istemci tarafında kesinlikle .NET Framework yüklü olması gerekmiyor!

Gelen yenilikler...

Silverlight 2.0 ile beraber artık Silverlight uygulamaları programlarken VB, C#, JavaScript, IronPyhton ve IronRuby dillerini kullanabilirsiniz.

1.0 sürümünde eksik olan ana form kontrollerinin RunTime'a eklenmesinin yanı sıra Layout kontrolleri, Calendar gibi özel kontroller ve DataGrid gibi veri kontrolleri de kullanımımıza sunuluyor. Tüm bu kontrollerin tasarımları ile ilgili WPF'den de alışık olduğumuz şablonlama yapısı kullanılabilir.

Silverlight 2.0 ile REST, WS*/SOAP, POX, RSS, ve HTTP kullanılarak farklı verilere ulaşmak mümkün. Bu çerçevede Cross-Domain-Request için de Policy File aracılığı ile destek sağlanıyor.

Aslında Silverlight 2.0 ile gelen Core CLR .NET'te alışık olduğumuzdan pek farklı değil. İstemci tarafında çalışacağımız için HTML/DOM entegrasyonu, LINQ ve özellikle XLINQ gibi tüm yapılar Silverlight 2.0 içerisinde de mevcut.

Gelecek neler getirecek?

AJAX Control Toolkit'i hatırlayanlarınız vardır. Aynı şekilde WPF için de bir control toolkit çıkarıldı. Şimdi de sıra Silverlight tarafında. "Silverlight Control Pack" adı verilen paket CodePlex üzerinden yayınlanacak TreeView gibi güzel kontroller olacak. Paket tamamen açık kaynaklı olarak yayınlanacak.

Eclipse özellikle Cross-Platform bir yazılım geliştirme aracı olarak bilinen IDE'lerden biri. Microsoft sponsorluğunda ilerleyen Soyotec'e ait bir proje ile Eclipse'e Silverlight geliştirme entegrasyonu uygulanacak. Ek olarak Microsoft Silverlight XAML'ının "Open Specification" olarak duyurdu, yani isteyenler bu XAML kodunu üreten veya yazan yazılımlar üretebilecekler.

Araçlar nerede?

Her zamanki gibi Visual Studio üzerinde "Silverlight Tools" paketini kurmanız gerekiyor. Bu paket ile beraber Silverlight SDK, proje şablonları, Intellisense desteği gibi noktlar Visual Studio'ya dahil oluyor. Sonrasında tabi ki Silverlight 2.0 uygulamalarını tasarımı için de Expression Blend'e ihtiyacımız var. Blend'in son yayınlanan sürümü olan 2.0 sürümü sadece Silverlight 1.0 destekliyor. Blend 2'ye Silverlight 2.0 desteğinin gelmesi için Blend 2 SP1'in yüklenmesi gerek. Silverlight 2.0 Beta 2 günlerini hatırlayan Blend 2.5'i de hatırlayacaklardır, artık 2.5 diye bir şey yok :)

Silverlight Tools for Visual Studio 2008 SP1 (72.1MB)
Microsoft Expression Blend 2 Service Pack 1 (17.8MB)
Deep Zoom Composer (3.8MB)

Silverlight 2.0 Tools paketi artık Visual Studio'nun Express sürümlerini de destekliyor. Yani Silverlight uygulamaları programlamak için çok kuvvetli ücretsiz bir alternatifiniz var.

Nasıl öğrenebilirim?

Silverlight 2.0 öğrenebilmeniz için başta Silverlight 2.0'ın desteklediği programlama dillerinden birini öğrenmeniz gerek. Bu noktada ağırlıklı olarak C# ve VB karşımıza çıkacaktır. Aşağıdaki adreste benim şu anda Silverlight 2.0 ile ilgili toplam 55 makalem var.

http://daron.yondem.com/tr/formatpage.aspx?path=liste.format.html#Silverlight

Makaleleri incelemeye başlarken Silverlight 2.0 seminerlerime ait videoları de SeminerTV bölümünden edinebilirsiniz. Çok yakında Silverlight 2.0 ile ilgili farklı detaylara yönelik seminer, ücretsiz eğitimleri de blogumdan duyuracağım.

Hepinize kolay gelsin!

Tuesday, October 14, 2008 11:06:29 AM (GTB Standard Time, UTC+02:00)  #    Comments [4]   Expression Blend | Silverlight 2.0 | Visual Studio 2008  | 
 Monday, October 13, 2008

Bir CEBIT daha geldi geçti, veya sadece bir FUAR daha geldi geçti. Ben de TBD'nin katkılarıyla CEBIT'te minik de olsa yer aldım. Bazen soranlar oldu "Hocam fuara gelelim mi?" Ben de cevapladım "Valla ben TBD'de oturumum olmasa gitmeyecektim, siz bilirsiniz" Peki neden? Buyurun sizi "Daron'un Fuar Eleştirileri Tarihi" sergisine davet ediyorum.

Yıl 2003, Yer: Bilişim Haritası Dergisi Sayfa 1

Bilişim Haritası Editör Yazısı

Yukarıda bundan beş yıl önce editörü olduğum ve Bilişim Fuarı'nda katılımcılara dağıtılan bir derginin ilk sayfasını görüyorsunuz. Gelin yolculuğumuza devam edelim.

Yıl: 2007, Yer: Daron Yöndem Blog

Blogumdan bir haykırış!

ve şimdi?

Görüyorum ki yavaş yavaş herkes bu iğrenç gidişatın farkına varmış. Geçenlerde FaceBook üzerinde birinin status yazısında "CEBIT balonuna ben yokum" şeklinde bir cümle görmüştüm. Merak etmeyin balonların işlevsiz olduğu gibi bir iddiam yok ama eğer benim CEBIT fuarını gezmem yaklaşık 12 dakika sürüyorsa ve girişte ödenen 20 YTL'den yola çıkarsak dakika başına 1YTL'den daha fazla ödeme yaparak giriyorsam :) ortada bir sorun var. (Parasında değilim, maksat metafor olsun)

Bu sorun ya benim kişisel sorunum ya de fuarın genel bir sorunu var. Geçen beş yıla bakarsak sanki benim kişisel sorunummuş gibi dursa da artık anlaşılıyor ki bu sorunun benle bir alakası yok :) sorun fuarın sorunu.

Gönül der ki : "Nerede Hannover CEBIT! nerede..."   

Kocaman CEBIT fuarını gezdim ve görmediğim, duymadığım, bilmediğim bir teknoloji ile karşılaşmadım! Açık ve net bir şekilde yine CEBIT panayırını / pazarını gezdim ve çıktım. Bu çerçevede CEBIT'te beni dinleyenlere, dinlemeye gelenlere özellikle teşekkür ediyorum. Siz olmasanız ben de gitmeyecektim :)

Kalın sağlıcakla...

Monday, October 13, 2008 3:22:51 PM (GTB Standard Time, UTC+02:00)  #    Comments [14]   Dertli Kerem  | 
 Sunday, October 12, 2008

Bir önceki yazımda yeni bir Dynamic Data Web Site'ın nasıl oluşturulabileceğine göz atmıştık. Aynı proje üzerinden devam ederek Dynamic Data Web Site'larda otomatik olarak karşımıza çıkan sayfaların yapılarını, nerelerden geldiklerini ve yönlendirme sistemlerini inceleyeceğiz.

Tamamen boş, yeni bir Dynamic Data Web Site yarattığınızda aslında Visual Studio sizin için birçok gerekli dosyayı projenize otomatik olarak ekliyor. Tüm bu otomatik eklenen dosyalar proje içerisinde DynamicData adında bir klasörün altında saklı.

DynamicData klasöründeki SAKLI GÜÇ
DynamicData klasöründeki SAKLI GÜÇ

Dynamic Data klasöründeki farklı yapıların amaçlarını hızlıca açıklayalım. Content klasörü altındaki içerik genelde diğer UserControl ve sayfalarda kullanılan içeriği taşır. Bu klasörde resimler veya harici UserControll'ler bulunabilir. Varsayılan ayarlarla gelen iki UserControl'den biri olan FilterUserControl bizim örneğimizde Kategorilerin filtreleme amaçlı olarak kullanıldığı yerlerde nasıl gözükeceğini ve çalışacağını belirler. FilterUserControl.ascx'in içindeki kod baktığımızda aşağıdaki manzara ile karşılaşıyoruz.

<%@ Control Language="VB" CodeFile="FilterUserControl.ascx.vb" Inherits="FilterUserControl" %>

 

<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" EnableViewState="true" CssClass="droplist">

    <asp:ListItem Text="All" Value="" />

</asp:DropDownList>

Bu kodda gördüğünüz DropDownList'i farklı bir kontrol ile değiştirirseniz doğrudan tüm proje içerisinde Filtreleme işlemlerinde bu kontrol kullanılacaktır. Sanırım yavaş yavaş Dynamic Data Web Site yapısının avantajlarını da hissetmeye başladık. Tabi bu gibi özelleştirme konularının detaylarına ileride daha derinlemesine gireceğiz.

DynamicData klasörümüzün içeriğine geri dönmek gerekirse sırada FieldTemplates klasörü vardı. Hatırlarsanız bir önceki makalemizde veritabanındaki tabloların Field'lerinin veri tipine göre farklı kontrollerin sahneye geldiğini görmüştük. Yerine göre MultiLine bir Textbox veya Chechbox gelebiliyordu. İşte FieldTemplates klasörü altında farklı veri tiplerine için sahneye gelecek olan UserControl'ler bulunuyor. Örneğin Boolean.ascx'i açarak karşımıza bir Checkbox gelecektir.

<%@ Control Language="VB" CodeFile="Boolean.ascx.vb" Inherits="BooleanField" %>

 

<asp:CheckBox runat="server" ID="CheckBox1" Enabled="false" />

Yine bu dosya içerisinde yapılan herhangi bir değişiklik tüm projede Boolean Field'lerin gösteriminde etkili olacaktır.

Son olarak bizi yakından ilgilendiren klasörlerden biri de PageTemplates klasörü. Bu klasör içerisinde veri kaynağımızdaki tüm tablolarla dinamik olarak çalışabilecek şekilde hazırlanmış ve CRUD işlemlerini yapmayı hedefleyen farklı ASPX sayfaları bulunuyor. Bu sayfalar bizim örneğimizde de hem Kategoriler hem de Ürünler tablosunu düzenlerken kullanılıyordu.

Dynamic Data Web Site'ın URL yapısı.
Dynamic Data Web Site'ın URL yapısı.

Yukarıdaki ekran görüntüsünde de görebileceğiniz gibi Kategorilers adındaki LINQ serisini düzenlerken düzenlediğimiz tablonun / nesnelerin adı URL içerisinde belirdikten sonra doğrudan List.aspx adında bir dosya çağrılıyor. Bu dosya hali hazırda PageTemplates içerisinde bulunan dosyanın ta kendisi. Bunun gibi Edit düğmesine tıkladığımızda da Edit.aspx ve tüm diğerleri de uygun işlemlerde tablo isminin ardından geliyorlar. Tabi ki URLRewriting'den bahsediyoruz ama konumuz o olmadığı için detaylara girmeyeceğim.

PageTemplates içerisinde herhangi bir dosyanın görselliğini veya yapısını değiştirdiğiniz anda projenizdeki tüm tablolarla ilgili işlemlerde gözükür hale gelecektir. Unutmayın tüm tablolar için bu dosyalar kullanılıyor. Peki bu durumu nasıl değiştirebiliriz?

Farklı tablolara farklı sayfalar?

Aslında tüm bu yönlendirme işlemlerinin yapıldığı yer projenin Global.asax dosyası. Global.asax içerisinde kodlar tabloların ne şekilde hangi dosyalarla işlem yapacağına karar veriyor.

[VB]

    routes.Add(New DynamicDataRoute("{table}/{action}.aspx") With { _

        .Constraints = New RouteValueDictionary(New With {.Action = "List|Details|Edit|Insert"}), _

        .Model = model})

[C#]

        routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {

            Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),

            Model = model

        });

Yukarıdaki gördüğünüz kod Global.asax içerisinde hazır olarak bulunuyor ve List, Details, Edit, Insert işlemlerinin hepsini tablo adı / aksiyon adı .aspx şeklinde yönlendiriyor. Aslında Dynamic Web Site yapısına gelen bir diğer özellik de tüm bu CRUD işlemlerinin tek bir sayfada yapılacak şekilde düzenlenmesi. Yani verileri ekleme, çıkarma ve düzenleme işlemlerinin hepsini tek bir sayfada halledebilecek şekilde hazırlanmış bir şablon da DynamicData klasöründeki PageTemplates içerisinde duruyor : ListDetails.aspx.

Bu dosya içerisindeki bir GridView Inline Editin sağlarken DetailsView'de detayların gösterilmesi ve yeni kayıt eklenmesini sağlıyor. Peki yönlendirmeyi nasıl değiştirebiliriz? Bu işlemin kodu de Global.asax içerisinde pasif bir şekilde duruyor. Tek yapmanız gereken yukarıdaki kodu pasif hale alıp aşağıdaki aktif hale getirmek.

[VB]

        routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _

            .Action = PageAction.List, _

            .ViewName = "ListDetails", _

            .Model = model})

 

        routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _

            .Action = PageAction.Details, _

            .ViewName = "ListDetails", _

            .Model = mod

[C#]

        routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")

        {

            Action = PageAction.List,

            ViewName = "ListDetails",

            Model = model

        });

 

        routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")

        {

            Action = PageAction.Details,

            ViewName = "ListDetails",

            Model = model

        });

Kodlarda da yer aldığı üzere toplam iki yönlendirme yapıyoruz. Birincisi "List" işleminin tablo adı / ListDetails.aspx sayfasında yapılacağı ile ilgili diğer ise Details görünümünün de aynı şekilde yapılacağı ile ilgili. Edit ve Insert işlemlerini yönlendirmemize gerek yok çünkü zaten onlar artık ListDetails içerisinde hallediliyor olacak.

ListDetails ile herşey aynı sayfada halloluyor.
ListDetails ile herşey aynı sayfada halloluyor.

Yukarıdaki ekran görüntüsünde ListDetails.aspx'i görüyorsunuz. GridView artık kendi içerisinde InlineEdit destekliyor ve bizim kategori kolonu da gördüğünüz gibi Edit modunda bir DropDownList olarak beliriyor.

Peki bizim esas konumuz neydi? Biz farklı bir tabloyu farklı bir dosya ile göstermek istiyorduk. Gelin örneğimizdeki Urunler tablosunun ListDetails ile gösterilmesini ayarlarken geri kalanların normal bir şekilde ayrı ayrı dosyalarla düzenlenmesini sağlayalım.

[VB]

        routes.Add(New DynamicDataRoute("Urunlers/ListDetails.aspx") With { _

            .Action = PageAction.List, _

            .ViewName = "ListDetails", _

            .Table = "Urunlers", _

            .Model = model})

 

        routes.Add(New DynamicDataRoute("Urunlers/ListDetails.aspx") With { _

            .Action = PageAction.Details, _

            .ViewName = "ListDetails", _

            .Table = "Urunlers", _

            .Model = model})

 

        routes.Add(New DynamicDataRoute("{table}/{action}.aspx") With { _

            .Constraints = New RouteValueDictionary(New With {.Action = "List|Details|Edit|Insert"}), _

            .Model = model})

[C#]

        routes.Add(new DynamicDataRoute("Urunlers/ListDetails.aspx")

        {

            Action = PageAction.List,

            ViewName = "ListDetails",

            Table = "Urunlers",

            Model = model

        });

 

        routes.Add(new DynamicDataRoute("Urunlers/ListDetails.aspx")

        {

            Action = PageAction.Details,

            ViewName = "ListDetails",

            Table = "Urunlers",

            Model = model

        });

 

        routes.Add(new DynamicDataRoute("{table}/{action}.aspx")

        {

            Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),

            Model = model

        });

Yukarıdaki kodlar Urunlers tablosunun ListDetails.aspx ile gösterilmesini ve geri kalan tüm tabloların standart bir şekilde tablo adı / aksiyon adı.aspx ile düzenlenmesini sağlayacaktır. Burada önemli olan noktalardan biri kodumuzun içerisindeki istisnai durumların yani bizim örneğimizde Urunlers tablosunun durumunun kod sırasında daha önde tanımlanmış olmasının şart olması. Aksi halde sistem istediğimiz gibi çalışmayacaktır.

Bu yazıda Dynamic Web Site yapısının nasıl çalıştığını ve proje yapısını incelemekle beraber web sitelerini özelleştirme dünyasına da ufak bir giriş yaptık. Sonraki yazılarımda derin detaylara yolculuğumuz devam edecek.

Hepinize kolay gelsin.

Sunday, October 12, 2008 12:28:25 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   ASP.NET 3.5  | 
 Saturday, October 11, 2008

ASP.NET tarafında programlama yaparken çoğu zaman yaptığımız işlemlerin veya kullanıcılara sağlamaya çalıştığımız ortamında sadece CRUD (Create, Read, Update, Delete) operasyonlarını yapmakla yükümlü olduğunu farkına bile varmayız. Aslında tüm yaptığımız sürekli farklı toplolar için INSERT, UPDATE, DELETE işlemlerini yapan sayfalar, arayüzler ve kodlar yaratmaktır. Bazen bu kodların tabloların niteliğine göre biraz değişir bazen de tablolar arası ilişkiler nedeniyle ek filtrelemeler koymamız gerekir. Fakat özünde baktığımızda işin büyük kısmı ve sürekli tekrar etmekten bir programcı olarak genelde sıkıldığımız kısmı klasik CRUD işlemleridir.

İşte tam da bu noktada bizim sorunumuzu çözecek olarak yapı .NET Framework 3.5 SP1 ile beraber artık Visual Studio'nun içerisinde: ASP.NET Dynamic Data Web Site!

Önce bir hazırlanalım!

Nesne Tabanlı Tasarım mimarisinin mantığına tamamen aykırı olsa da maalesef çoğu projede hala öncelikle veritabanı tasarımını yaparak ilerliyoruz. Bu kötü bir alışkanlık gibi gözükse de ufak projelerde çok sorun yaratmayacağını öngörebiliriz. Dynamic Data Web Site mantığında da önce elinizde hazır bir veritabanı olması şart. Bunun için hemen hızlı bir şekilde SQL 2008'de örnek bir veri tabanı yaratacağız.

Örneğimizdeki veritabanının tasarımı.
Örneğimizdeki veritabanının tasarımı.

Veritabanımızı yukarıdaki şemaya göre yarattıktan sonra artık hemen bu veritabanını kontrol edecek olan web sitesini yaratmak üzere Visual Studio tarafına geçebiliriz.

Yeni bir Dynamic Web Site!

Visual Studio içerisinde "File / New Web Site" menüsüne ufak bir yolculuk yaparsak karşımıza seçenekler arasında bir de "Dynamic Data Web Site"ın geldiğini göreceğiz. Hemen bu seçeneği işaretleyerek yeni web sitemizi yaratalım.

Projenizi yarattıktan sonra "Solution Explorer" içerisinde gördüğünüz farklı klasör ve dosyalar aklınızı karıştırmasın. Bu konulara ileriki makalelerde detaylı olarak değineceğiz. Şu an için önemli olan hemen web sitemizi veritabanı ile ilişkilendirerek ayağa kaldırıp sonuca ulaşmak.

Dynamic Data Web Site'ın veritabanına ulaşması için Entity Framework kullanabileceğiniz gibi rahatlıkla LINQ2SQL sınıflarından da faydalanabilirsiniz. Biz örneğimizde LINQ2SQL kullanacağız. Bu nedenle hemen yeni bir DBML dosyasını projemize ekliyoruz ve veritabanımızdan "Kategoriler" ve "Ürünler" tablolarını DBML dosyasına taşıyoruz.

LINQ2SQL'in detayların bu yazıda girmeyeceğim, merak edenler bu konudaki detayları "LINQ2SQL'e Giriş" yazımdan edinebilirler.

Artık LINQ2SQL sınıflarımız da hazır olduğuna göre geriye sadece tek bir nokta kalıyor; Dynamic Data Web Site'ı LINQ2SQL sınıflarımız ile haberleştirmek. Bu işlemi yapabilmemiz için gerekli kod aslında hazır bir şekilde projenin Global.asax dosyasında duruyor.

    '                    IMPORTANT: DATA MODEL REGISTRATION

    ' Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data

    ' model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true only if you are sure

    ' that you want all tables in the data model to support a scaffold (i.e. templates)

    ' view. To control scaffolding for individual tables, create a partial class for

    ' the table and apply the [Scaffold(true)] attribute to the partial class.

    ' Note: Make sure that you change "YourDataContextType" to the name of the data context

    ' class in your application.

    ' model.RegisterContext(GetType(YourDataContextType), New ContextConfiguration() With {.ScaffoldAllTables = False})

Yukarıdaki gibi tamamen pasif hale getirilmiş bir paragraf yazı ve bir satır kod Global.asax'ın en başında yer alıyor. Bizim için önemli olan en alttaki kod satırı tabi ki. Bu satırı aktif hale getirerek YouDataContextType'ın yerine kendi DBML dosyamızın DataContext'ini atamamız gerek. Sonrasında da ScaffoldAllTables özelliğini False değerinden True'ye çevirmeliyiz.

[VB]

model.RegisterContext(GetType(DataClassesDataContext), New ContextConfiguration() With {.ScaffoldAllTables = True})

[C#]

model.RegisterContext(typeof(DataClassesDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

Son olarak yukarıdaki kod işimizi görecektir. Burada özellikle açıklanması gereken nokta sanırım ScaffoldAllTables özelliği. Bu özellik sayesinde Dynamic Data Web Site hedef veritabanındaki (Şu anda sadece LINQ2SQL'in sağladığı tablolar) tüm tablolara ulaşarak gerekli CRUD işlemlerinin yapılabilmesini sağlayacaktır. Bu işlemin yapılıp yapılmayacağına isterseniz tablo bazında da karar verebilirsiniz, fakat bunun detaylarına daha ileride gireceğiz.

Şimdi son değişikliklerle beraber Global.asax dosyamızı da kaydedelim ve projemizi çalıştıralım :)

Dynamic Data Web Site'ın ilk görünümü.
Dynamic Data Web Site'ın ilk görünümü.

Gördüğünüz gibi site çalıştığında anda kendisine bağlı tüm tabloları hemen listeledi. Şimdi hızlıca bir Kategorilers sayfasına yönelelim. Unutmadan, buradaki isimlerin LINQ2SQL'deki nesne isimleri olduklarını hatırlamakta fayda var, isterseniz bu isimleri LINQ2SQL tarafından rahatlıkla değiştirebilirsiniz, başka seçenekler de var ama onları da ileride inceleyeceğiz.

Kategoriler tablosu listeleniyor.
Kategoriler tablosu listeleniyor.

Benim daha önce veritabanına girişini yaptığın birkaç veriyi yukarıdaki ekranda görebilirsiniz. Gördüğünüz gibi otomatik olarak tüm bu kategoriler için Edit / Delete ve Details bölümleri açılmış. Kategoriler'in Aciklama özellikleri burada gösterilmemiş ve Details bölümü ile gidilen sayfaya saklanmış. Daha da güzeli her kategorinin yanına bir "View Urunlers" linki konarak bu kategorideki ürünlerin görülebileceği sayfaya birer de link konmuş. Eh gönül daha ne ister?

Ürünler'in gösterildiği Dynamic Data Sayfası
Ürünler'in gösterildiği Dynamic Data Sayfası

Ürünlerin gösterildiği sayfaya gittiğimizde ise otomatik olarak Kategoriler'in bir DropDownList'e dönüştüğünü ve filtreleme amaçlı olarak kullanılabildiğini görüyoruz. Ayrıca burada da hem yeni ürün ekleme amaçlı hem de düzenleme için gerekli tüm detaylar hazırlanmış.

Ürünler'imizin detaylarını düzenleyebileceğimiz sayfalar da hazır.
Ürünler'imizin detaylarını düzenleyebileceğimiz sayfalar da hazır.

Herhangi bir ürüne ait Edit linkine tıkladığımızda gittiğimiz sayfada Urunler tablosundaki her bir Field'e uygun şekilde gerekli görsel öğelerin yaratıldığını görebiliyoruz. Veritabanına NText olarak düzenlediğimiz yerler MultiLine TextBox'lar haline gelirken kategorilerimiz de bir DropDownList haline gelmiş.

Tabi ki bu web sitesi bu şekilde kullanılabileceği gibi özelleştirmelerin gerekeceği de kesin. Sonraki Dynamic Data ile ilgili yazılarımda özelleştirmelerle ilgili detayların yanı sıra arka plandaki mekanizmaları da inceleyeceğiz.

Hepinize kolay gelsin.

Saturday, October 11, 2008 11:22:06 AM (GTB Standard Time, UTC+02:00)  #    Comments [5]   ASP.NET 3.5  | 
 Friday, October 10, 2008

Bugün yine CEBIT'te TBD'nin organizasyonunda "Geek Zone"da konuşmacıydım. Bu sefer konu "WPF ile 3D Animasyon Programlama" şeklindeydi. 25 dakikalık bir sunumda tam gaz 3D animasyon dünyasına girip hızlı bir şekilde bu animasyonların programatik kontrolünü de gördük. Gerçekten SnapShot kıvamında bu oturumlar çok ilginç, aslında katılımcıların yorumlarını duymak gerek :)

Geek Zone'da WPF ile 3D Animasyon Programlama oturumum.
Geek Zone'da WPF ile 3D Animasyon Programlama oturumum.

Ayakta kalanlardan özür diliyoruz, ortamımız biraz ufaktı. Aldığım duyumlara göre seneye Geek Zone'un alanı çok daha geniş olacakmış. Katılan herkese çok teşekkürler.

Söz verdiğim üzere yaptığımız uygulamanın kodlarını aşağıdan indirebilirsiniz.

Oturuma ait uygulamanın kaynak kodları - 10102008_2.rar (355,22 KB)
Friday, October 10, 2008 4:15:48 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]   Seminer | WPF  | 
 Thursday, October 09, 2008

Silverlight 2.0'ın RC0 olması ile beraber tabi ki her şey yenilendi. ve bu yenilikleri takiben "Offline Documentation" paketinin de yenilenmesinin zamanı gelmişti. Aşağıdaki linkten Silverlight 2.0'ın tüm SDK paketini internete bağlı olmadan da kullanılabilecek CHM formatında indirebilirsiniz.

http://go.microsoft.com/fwlink/?LinkID=127106

Özellikle Vista kullanıcıları için ufak bir uyarıda bulunmak istiyorum. Vista'da CHM dosyalarını açtığınızda ekran boş kalıyorsa hemen dosyaya sağ tuş tıklayarak "Properties" kısmına geçip "Unblock" düğmesine basın. Sonrasında dosyayı tekrar açtığında herhangi bir sorun olmayacaktır.

Hepinize kolay gelsin.

Thursday, October 09, 2008 5:31:49 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Silverlight 2.0  | 
 Wednesday, October 08, 2008

.NET Framework 3.5 SP1 ile beraber gelen en büyük yeniliklerden biri de PixelShader kullanımının artık WPF uygulamalarında rahat bir şekilde mümkün olması. Kendi PixelShader efektlerinizi yazabileceğiniz gibi hazır kütüphanelerden de faydalanabilirsiniz. Bu yazımızda içerisinde hem normal PixelShader efektleri hem de geçiş efektleri barındıran CodePlex üzerindeki Windows Presentation Foundation Pixel Shader Effects Library kütüphanesini kullanarak efektlerin nasıl uygulandığını inceleyeceğiz.

Hazırlığımızı yapalım.

CodePlex üzerindeki Pixel Shader kütüphanesini kullanabilmemiz için öncesinde bir de Shader Effects BuildTask ve şablonlarını kurmamız gerek. Bu eklentiler doğrudan Pixel Shader efektlerinin programlanmasında kullanılıyor. Biz kendi Pixel Shader efektlerimizi programlamayacak olsak da diğer kütüphane bu eklentileri kullandığı için bilgisayarımıza kurmamız şart.

WPF Futures içerisinde bulunan Shader Effects BuildTask and Templates.zip yüklemesini aşağıdaki adresten bilgisayarınıza indirebilirsiniz.

http://www.codeplex.com/wpf/

İndirdiğiniz bu paket içerisindeki ShaderBuildTaskSetup.msi dosyasını çalıştırarak hemen kurulumu tamamlayın. Sonrasında da isterseniz Pixel Shader programlama için kullanılan şablonları da bilgisayarınıza yükleyebilirsiniz. Bunun için yükleme paketindeki Templates.zip dosyasını C:\Users\Daron\Documents\Visual Studio 2008 klasöre açmanız gerek. Bu klasör tabi ki sizin bilgisayarınızdaki kullanıcı adına göre değişecektir.

Pixel Shader Effects Library

Sıra geldi Pixel Shader Effects Library paketini CodePlex üzerinden indirmeye. Aşağıdaki adresten tüm paketi bilgisayarınıza indirip kaynak kodları ile beraber yazılmış Pixel Shader efektlerini inceleyebilir hatta paket içerisinde gelen örnek uygulamayı da kullanıp kaynak kodlarını inceleyebilirsiniz.

http://www.codeplex.com/wpffx

Yükleme paketi içerisindeki Visual Studio Solution dosyasını açarsanız karşınıza 3 ayrı proje gelecektir. "ShaderDemoApp" projesi klasik bir WPF projesi. Bu proje birazdan bahsedeceğimiz iki projeyi referans olarak alıp demo amacıyla hazırlanmış durumda. Ayrıca Solution içerisinde bir ShaderEffectLibrary bir de TransitionEffects adında projeler var. Bu projelerin her biri harici DLL kütüphaneleri halinde Compile ediliyor. ShaderEffectLibrary içerisinde standart PixelShader efektleri varken TransitionEffects içerisinde ise Pixel Shader kullanılarak hazırlanmış geçiş efektleri var.

Bu paketlerini farklı projeler içerisinde kullanmak için ister ihtiyacınız olan kütüphanenin projesini kendi solution'larınıza da ekleyin ister örnek proje üzerinden bu kütüphaneleri Compile ederek doğrudan DLL'lerini alarak farklı projelerde kullanın. Karar tamamen size kalmış.

TransitionEffects Kullanımı

Beni ilk heyecanlandıran videolar arası geçiş efektleri olduğu için hemen TransitionEffects kütüphanesinden başlayacağım. Yeni bir WPF projesi yaratarak bir önceki adımda indirdiğimiz paket içerisinde TransitionEffects projesini söz konusu WPF projesi ile aynı Solution içerisine yerleştirdim. Sonrasında WPF projesine de sağ tıklayarak "Add Reference" diyip TransitionEffects projesini WPF'e reference olarak ekledim. Böylece tüm geçiş efektlerini kullanma şansımız olacak.

Videolar arası geçiş yapacağımız için iki ayrı videoyu göstermek üzere uygulamama iki adet MediaElement ekliyorum.

<Window x:Class="Window1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      Title="Window1"

      Height="300"

      Width="300">

  <Grid>

    <MediaElement x:Name="Birinci"

                Source="Butterfly.wmv"

                Panel.ZIndex="1" />

    <MediaElement x:Name="Ikinci"

                Source="Bear.wmv"

                Opacity="1"

                Visibility="Visible"

                Panel.ZIndex="0" />

    <Button HorizontalAlignment="Right"

          Margin="0,0,8,8"

          VerticalAlignment="Bottom"

          Width="73"

          Height="27"

          Content="Button"

          x:Name="Dugme" />

  </Grid>

</Window>

İki MediaElement ve bir de Button olan formumuza ait XAML kodunu yukarıda inceleyebilirsiniz. Bu noktada hemen dikkat etmemiz gereken şeylerden biri MediaElement'lerin ZIndex özellikleri. Hangi videonun arkada hangisinin önde olduğuna ZIndex ile karar verdim. Bunun nedeni birazdan kod ile bu sıralamayı değiştirecek olmam.

Uygulama çalıştırıldığında her iki MediaElement de farklı videolar oynatıyor olacaklar. Amacımız şu an önde olan MediaElement'ten arkadakine doğru bir geçiş efekti yaratmak.

[VB]

Me.Ikinci.SetValue(Grid.ZIndexProperty, 2)

[C#]

this.Ikinci.SetValue(Grid.ZIndexProperty, 2);

İlk olarak arkadaki MediaElement'imizi düğmeye basıldığı anda öne alıyoruz. Geçiş efektinin başlangıcında Ikinci adını verdiğimiz MediaElement otomatik olarak görünmez hale gelecek ve sonrasında da efekt ile ekranda gözükecek. Öne alma işlemini bitirdikten hemen sonra animasyonumuzu hazırlıyoruz.

[VB]

Dim Anim As New TransitionEffects.CloudRevealTransitionEffect

Dim da As New DoubleAnimation(0.0, 1.0, New Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd)

da.AccelerationRatio = 0.5

da.DecelerationRatio = 0.5

Anim.BeginAnimation(TransitionEffect.ProgressProperty, da)

[C#]

TransitionEffects.CloudRevealTransitionEffect Anim = new TransitionEffects.CloudRevealTransitionEffect();

DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd);

da.AccelerationRatio = 0.5;

da.DecelerationRatio = 0.5;

Anim.BeginAnimation(TransitionEffect.ProgressProperty, da);

Yukarıdaki kod içerisinde de görebileceğiniz gibi Anim adını verdiğimiz animasyonumuz doğrudan TransitionEffects kütüphanesinden CloudRevealTransitionEffect adındaki efektin ta kendisi. Tabi bu efekte bir de DoubleAnimation ayarlamamız gerek, DoubleAnimation içerisinde efektin Progress (İlerleme durumu) özelliğinin 0'dan 1'e kadar geleceğini ve bu işlemin 2 saniye süreceği belirtiyoruz. Diğer ayarlar efektin hızlanma ve yavaşlama etkenleri ile ilgili.

Son olarak BeginAnimation metoduna da Dependency'miz olan ProgressProperty'yi ve DoubleAnimation nesnemizi veriyoruz. Toplamda baktığımızda DoubleAnimation üzerinden efektin sürecinin uzunluğunu belirleyerek efekti başlatmış olduk.

[VB]

Dim vb As New VisualBrush(Me.Ikinci)

vb.Viewbox = New Rect(0, 0, Me.Ikinci.ActualWidth, Me.Ikinci.ActualHeight)

vb.ViewboxUnits = BrushMappingMode.Absolute

[C#]

VisualBrush vb = new VisualBrush(this.Ikinci);

vb.Viewbox = new Rect(0, 0, this.Ikinci.ActualWidth, this.Ikinci.ActualHeight);

vb.ViewboxUnits = BrushMappingMode.Absolute;

Efekt süregelirken ekrandaki boyama işleminin yapılabilmesi için bi VisualBrush ayarlıyoruz. Bu VisualBrush doğrudan bizim Ikinci adındaki efekte uğrayacak MediaElement'e bağlanıyor. VisualBrush'ın genişlik ve yüksekliğini de ayarladıktan sonra artık kendisini Anim değişkenimize teslim edebiliriz.

[VB]

        Anim.OldImage = vb

        Me.Ikinci.Effect = Anim

[C#]

Anim.OldImage = vb;

this.Ikinci.Effect = Anim;

OldImage özelliği üzerinden VisualBrush'ı da aktardıktan sonra Ikinci adındaki MediaElement'e BitMapEffect olarak animasyonumuzu eşitliyoruz. Hepsi bu kadar :) Yapının biraz karışık olduğunu itiraf etmeliyim, Pixel Shader Effects kütüphanesinin kullanımı ÇOK kolay değil fakat yaptığı işi daha önceleri nasıl yapabileceğimiz ile karşılaştırırsak aslında gerçekten çok büyük bir yük kaldırdığını söyleyebiliriz.

Aşağıdaki kodu çalıştırdığınızda istediğiniz geçiş efekti ile gerçek zamanlı olarak iki video oynarken birbirleri arasında geçişler yapabildiğinizi göreceksiniz.

[VB]

    Private Sub Dugme_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Dugme.Click

        Me.Ikinci.SetValue(Grid.ZIndexProperty, 2)

 

        Dim Anim As New TransitionEffects.CloudRevealTransitionEffect

 

        Dim da As New DoubleAnimation(0.0, 1.0, New Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd)

        da.AccelerationRatio = 0.5

        da.DecelerationRatio = 0.5

        Anim.BeginAnimation(TransitionEffect.ProgressProperty, da)

 

        Dim vb As New VisualBrush(Me.Ikinci)

        vb.Viewbox = New Rect(0, 0, Me.Ikinci.ActualWidth, Me.Ikinci.ActualHeight)

        vb.ViewboxUnits = BrushMappingMode.Absolute

 

        Anim.OldImage = vb

        Me.Ikinci.Effect = Anim

    End Sub

[C#]

        void Dugme_Click(object sender, RoutedEventArgs e)

        {

 

            this.Ikinci.SetValue(Grid.ZIndexProperty, 2);

 

            TransitionEffects.CloudRevealTransitionEffect Anim = new TransitionEffects.CloudRevealTransitionEffect();

 

            DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd);

            da.AccelerationRatio = 0.5;

            da.DecelerationRatio = 0.5;

            Anim.BeginAnimation(TransitionEffect.ProgressProperty, da);

 

            VisualBrush vb = new VisualBrush(this.Ikinci);

            vb.Viewbox = new Rect(0, 0, this.Ikinci.ActualWidth, this.Ikinci.ActualHeight);

            vb.ViewboxUnits = BrushMappingMode.Absolute;

 

            Anim.OldImage = vb;

            this.Ikinci.Effect = Anim;

 

        }

ShaderEffects Library Kullanımı

Bir önceki bölümde geçiş efektlerini kullanırken indirdiğimiz paket içerisinden TransitionEffect projesini kopyalamıştık. Bu sefer de söz konusu paketten ShaderEffects projesini kopyalıyoruz ve kendi yarattığımız bir WPF projesi ile aynı Solution içerisine alıyoruz. Sonrasında WPF projesine sağ tıklayarak "Add Reference" diyip ShaderEffects projesini WPF'e reference olarak tanımlıyoruz. Böylece artık WPF projemizde ShaderEffects kütüphanesini rahatlıkla kullanabiliriz.

Örneğimizde hemen bir MediaElement yerleştirelim ve bu MediaElement içerisinde oynatılan videolara Pixel Shader efektleri uygulayalım.

<Window x:Class="Window1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      Title="Window1"

      Height="300"

      Width="300">

  <Grid>

    <MediaElement x:Name="Birinci"

                Source="Butterfly.wmv" />

  </Grid>

</Window>

Uygulamamız açıldığı gibi istediğimiz efekti MediaElement'e uygulamak için aslında tek yapmamız gereken uygun efekti ayarları ile ürettikten sonra Birinci adındaki MediaElement'in Effect özelliğine eşitleyerek BitmapEffect olarak atamak.

[VB]

Dim Emboss As New ShaderEffectLibrary.EmbossedEffect

Emboss.Amount = 20

Birinci.Effect = Emboss

[C#]

ShaderEffectLibrary.EmbossedEffect Emboss = new ShaderEffectLibrary.EmbossedEffect();

Emboss.Amount = 20;

Birinci.Effect = Emboss;

Hepsi bu kadar. Onlarca efekt arasında istediğinizi seçip her efektin kendine özel ayarlarını da yaptıktan sonra ister bu efektleri bir MediaElement'e ister Image nesnesine bağlayabilirsiniz. Hatta dağa da ileri gidip Container Element'lerine bile bu gibi efektler verebilirsiniz.

Hepinize kolay gelsin.

Wednesday, October 08, 2008 3:59:48 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   WPF  | 
 Tuesday, October 07, 2008

Bugün CEBIT fuarında TBDGenc organizasyonundaki Geek Zone dahilinde "Facebook Uygulama Geliştirme" oturumunu sundum. Geek Zone'un konsepti gereği 20 dakikalık oturumlar gerçekleşiyor. Benim oturumu çaktırmadan 30 dakikaya kadar uzattım :)

Geek Zone'daki "Facebook Uygulama Geliştirme" oturumum.
Geek Zone'daki "Facebook Uygulama Geliştirme" oturumum.

Gerçek anlamda "hap" niteliğinde bir oturum oldu, eğer anlattığım her kelimeyi katılımcılara doğru şekilde aktarabildiysem ASP.NET ile FaceBook için uygulama geliştirme yolunda neredeyse karşılaşabilecekleri tüm soruları çözdük diyebilirim.

Aktivite de söz verdiğim üzere kullandığım sunumu aşağıdan indirebilirsiniz ;)

Facebook Uygulama Geliştirme Sunumu - 07102008_2.pptx (807 KB)

Cuma günü "WPF ile 3D animasyonları" anlatıyor olacağım. Sonrasında da CEBIT fuarını gezeceğim :) Bugün gezemedim. Hepinizi beklerim.

Tuesday, October 07, 2008 9:32:53 PM (GTB Standard Time, UTC+02:00)  #    Comments [9]   ASP.NET 3.5  | 
 Monday, October 06, 2008

Panoramic fotoğraf çekmek benim en sevdiğim hobilerimden biridir. Fotoğraf çekmeyi zaten severim, hatta çoğu turistik gezimin amacı fotoğraf çekmektir. Kulağa garip gelebilir fakat sadece fotoğrafını çekmek için gittiğim yerler var :) Neyse, konuya dönelik. Çektikten sonra baktığımda en mutlu olduğum fotoğraflar genelde ya panoramik ya da makro fotoğraflardır. Panoramik derken tabi ki binlerce dolarlık cihazlardan bahsetmiyorum, standart bir fotoğraf makinesi ile birden çok fotoğrafın çekilerek bilgisayarda birleştirilmesinden bahsediyorum. Eh benim fotoğrafçılığım bu kadar :)

Peki neden bu kadar geyik yaptım? Panoramik fotoğraf birleştirmek konusunda Exposure ayarlaması da yapabilen ücretsiz "adam akıllı" program yok :) (tu). Artık var.

Microsoft Research ekibinin yayınladığı ücretsiz bir araç olan Microsoft Image Composite Editor birden çok fotoğrafı alarak Exposure geçişlerini de ayarlayabiliyor. Yazılımın gerçekten ilginç özellikleri var.

Uygulama;

  • Silverlight DeepZoom projesi çıktısı verebiliyor, büyük panoramik fotolar için süper!
  • Photoshop Layer'lı PSD dosyası çıktısı alınabiliyor.
  • 360 derecelik birleştirme yapabiliyor.
  • HD Video web sitesi yaratabiliyor.
  • 64 bit destekli sürümü ile müthiş performans sunabiliyor.
  • GPU'nuzu kullanabiliyor!

Programı bilgisayarınıza indirmek ve hemen kullanmak için aşağıdaki adresi ziyaret etmeniz yeterli.

http://research.microsoft.com/ivm/ice.html

Monday, October 06, 2008 9:18:34 PM (GTB Standard Time, UTC+02:00)  #    Comments [4]   Silverlight 2.0  | 
 Sunday, October 05, 2008

.NET Framework'ün ufak bir paketini içerse de Silverlight ile web tarayıcısı içerisinde büyük mucizeler yaratmak mümkün. .NET'in JavaScript gibi scripting dillerine kıyasla işlemci kullanımındaki hakimiyetini de düşündüğümüzde istemci tarafında yapacağımız işlemlerin yoğunluğun artacağı kesin. Tüm bu işlemler süresince tabi ki kullanıcıları da bilgilendirmemiz gerekiyor. AJAX ile az çok web tarafında da alıştığımız "Loading" GIF'lerinin yerine Silverlight tarafında RC0 ile beraber artık ProgressBar kontrolümüz var.

<UserControl x:Class="SilverlightApplication7.Page"

            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

            Width="400"

            Height="300">

  <Grid x:Name="LayoutRoot"

        Background="White">

    <ProgressBar Height="28"

                VerticalAlignment="Top"

                Margin="40,58,29,0"/>

  </Grid>

</UserControl>

Standart bir ProgressBar'ı yukarıdaki XAML kodu ile uygulamanıza ekleyebilirsiniz. Aslında Silverlight içerisinde ProgressBar'ın Winforms'daki muadilinden ilk bakışta pek bir farkı yok. ProgressBar'ın Value özelliği o anki değeri, Maximum özelliği ise alabileceği en yüksek değeri tanımlıyor.

Gelin ufak bir örnek yapmak için bir DispatcherTimer kullanalım. Timer'ımızın iki saniyede bir ProgressBar'ı biraz ilerletsin. Böylece işlem yapılıyormuş gibi ProgressBar'ı izleyebilelim.

Partial Public Class Page

    Inherits UserControl

 

    WithEvents Timer As New System.Windows.Threading.DispatcherTimer

 

    Public Sub New()

        InitializeComponent()

    End Sub

 

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Progress.Maximum = 20

        Timer.Interval = New TimeSpan(0, 0, 2)

        Timer.Start()

    End Sub

 

    Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick

        Progress.Value += 1

    End Sub

End Class

Yukarıdaki kod ile Progress adındaki ProgressBar'ımızı oynattığımızda aşağıdaki görüntü ile karşılaşıyoruz.

ProgressBar iş başında.
ProgressBar iş başında.

Eğer gerçekten yapılacak işlemin ne kadar süreceği bilmiyorsanız ve bir şekilde bu bilgiyi kullanıcıya gösterme şansınız yoksa bu sefer de işlemin sürdüğüne dair bir gösterge olarak ProgressBar'ı kullanmak için IsIndeterminate özelliğini True olarak ayarlayabilirsiniz.

<ProgressBar Height="28"

            VerticalAlignment="Top"

            Margin="40,58,29,0"

            x:Name="Progress"

            IsIndeterminate="True"/>

Böyle bir durumda ProgressBar içerisinde sürekli olarak aynı animasyon çalıştırılacaktır.

ProgressBar sonsuz döngüde!
ProgressBar sonsuz döngüde!

ProgressBar'ın görselliğini değiştirmek için Foreground ve Background özelliklerinden faydalanabilirsiniz. Foreground özelliği ProgressBar içerisinde dolu kısımları etkilerken Background ise ProgressBar'ın boş olan kısımlarını etkileyecektir.

<ProgressBar

            x:Name="Progress">

  <ProgressBar.Background>

    <ImageBrush

                ImageSource="Garden.jpg"/>

  </ProgressBar.Background>

</ProgressBar>

Örneğin yukarıdaki kod ile aşağıdaki şekilde bir ProgressBar'ın fonuna bir fotoğraf yerleştirebilirsiniz. Hatta Background için bir ImageBrush yerine VideoBrush kullanarak farklı uygulamalar da oluşturulabilir. Burada özellikle Indeterminate ile ilgili dikkat etmek gerek. Indeterminate aktif hale geldiğinde Silverlight içerisinde ProgressBar'ın ForeGround'u ile tüm kontrol kaplanıyor ve üzerinden beyaz dikey Gradient'lar animasyon ile geçiriliyor. Bu sistem ancak ProgressBar'ın ControlTemplate'i özelleştirilebilirse değiştirilebiliyor aksi halde tüm standart ProgressBar kontrolleri bu şekilde çalışıyor.

Hepinize kolay gelsin.

Sunday, October 05, 2008 8:05:41 PM (GTB Standard Time, UTC+02:00)  #    Comments [2]   Silverlight 2.0  | 
 Saturday, October 04, 2008

Önümüzdeki hafta CEBIT fuarının haftası. CEBIT fuarı çerçevesinde TBDGENC'nin düzenlediği GeekZone aktivitesinde ben de iki oturumda konuşmacı olacağım. İşleyeceğimiz konulardan ilki "FaceBook'da Uygulama Geliştirme" ikincisi ise "WPF ile 3D Animasyonlar". GeekZone'da her bir oturum hap niteliğinde sadece 20 dakika sürüyor. Bana MCT eğitimlerindeki 5 dakikalık sunumlarımızı hatırlattı :)

GeekZone programını aşağıda inceleyebilirsiniz.

GeekZone Programı
GeekZone Programı

Saturday, October 04, 2008 3:44:19 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]   ASP.NET 3.5 | Seminer | WPF  | 
 Friday, October 03, 2008

Bugünlerde INETA Capital Hit ile ilgili aldığım maillerin neredeyse hepsi ulaşım olanakları ile ilgili. Ben de bu durum üzerine aktivitenin Çankaya Üniversitesi tarafındaki organizasyonunda bize yardımcı olan sevgili MSP, Çağrı Erdoğan'dan bazı bilgileri aldım :)

  • Uçak yolu ile Ankara'ya ulaşacak olanlar Havaş otobüsleri (10YTL) ile Aşti (Otogar)'a gelebilirler. Aşti'den Mavi 100.Yıl dolmuşları ile rahatlıkla Çankaya Üniversitesi'ne ulaşabilirler.
  • Otobüs yolu ile gelenler yine Aşti'den (Otogar) Mavi 100.Yıl dolmuşları ile Çankaya Üniversitesi'ne ulaşabilirler.
  • Ulusoy ile gelenler SöğütÖzü (Armada)'da inerek yine Mavi 100.Yıl dolmuşları ile Çankaya Üniversitesi'ne ulaşabilirler.
  • Kızılaydan gelenler ise 132 numaralı otobüsler ile doğrudan üniversiteye gelebilir.

Çankaya Üniversitesi ulaşım krokisi.
Çankaya Üniversitesi ulaşım krokisi.

Friday, October 03, 2008 3:16:30 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]   Seminer  | 
 Thursday, October 02, 2008

Silverlight 2.0 RC0 ile gelen yeni kontrollerden biri de ComboBox kontrolü. Bu yazımızda Combobox'ın kullanımına, görsel düzenlemelerin nasıl yapıldığında göz atacağız. İlk olarak yeni bir Silverlight projesi yaratalım ve Expression Blend 2 içerisinden Asslet Library'de bir Combobox bularak sahneye yerleştirelim.

<UserControl x:Class="SilverlightApplication5.Page"

            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

            Width="400"

            Height="300">

  <Grid x:Name="LayoutRoot"

        Background="White">

    <ComboBox HorizontalAlignment="Left"

              VerticalAlignment="Top"

              Width="157"

              Margin="38,43,0,0"/>

  </Grid>

</UserControl>

Yukarıdaki XAML kodu sahnede boş bir Combobox yaratacaktık. Combobox içerisine XAML kodu ile yeni öğeler eklemek istersek Combobox'ın Items dizisine ComboBoxItem'lar eklememiz gerekecek.

<ComboBox HorizontalAlignment="Left"

          VerticalAlignment="Top"

          Width="157"

          Margin="38,43,0,0">

  <ComboBox.Items>

    <ComboBoxItem Content="İlk Seçenek"></ComboBoxItem>

    <ComboBoxItem Content="İkinci Seçenek"></ComboBoxItem>

    <ComboBoxItem Content="Son Seçenek"></ComboBoxItem>

  </ComboBox.Items>

</ComboBox>

Her ComboBoxItem'ın ayrıca bir de IsSelected özelliği var. Böylece uygulama ilk çalıştırıldığında ve ComboBox sahneye ilk geldiğinde hangi Item'ın seçili olacağına karar verebilirsiniz.

<ComboBox HorizontalAlignment="Left"

          VerticalAlignment="Top"

          Width="157"

          Margin="38,43,0,0">

  <ComboBox.Items>

    <ComboBoxItem IsSelected="True"

                  Content="İlk Seçenek"></ComboBoxItem>

    <ComboBoxItem Content="İkinci Seçenek"></ComboBoxItem>

    <ComboBoxItem Content="Son Seçenek"></ComboBoxItem>

  </ComboBox.Items>

</ComboBox>

Tabi çoğu zaman bizler uygulamalarımızda bu şekilde seçenekleri XAML kodu içerisine gömmeyeceğiz. Genelde bir veri kaynağımız olacak ve veri kaynağındaki listelerin ComboBox içerisinde gösterilmesini tercih edeceğiz. Bu durumda gelin şimdi de ComboBox'a nasıl veri bağlayabileceğimizi inceleyelim.

İlk olarak Urun adında sınıfımızı tanımlayalım ve bu sınıf üzerinden örneğimizde kullanacağımız geçici veriyi üretelim.

[VB]

Class Urun

 

    Private PAdi As String

    Public Property Adi() As String

        Get

            Return PAdi

        End Get

        Set(ByVal value As String)

            PAdi = value

        End Set

    End Property

 

 

    Private PFiyat As Integer

    Public Property Fiyat() As Integer

        Get

            Return PFiyat

        End Get

        Set(ByVal value As Integer)

            PFiyat = value

        End Set

    End Property

 

End Class

[C#]

        public class Urun

        {

            private string PAdi;

            public string Adi

            {

                get { return PAdi; }

                set { PAdi = value; }

            }

 

 

            private int PFiyat;

            public int Fiyat

            {

                get { return PFiyat; }

                set { PFiyat = value; }

            }

        }

Uygulamamız ilk çalıştırıldığında yukarıda tanımladığımız Urun sınıfından nesneler yaratarak bir List değişkenine ekleyeceğiz. Sonra da bu listeyi ComboboxUrunler adını verdiğimiz Combobox'ımıza bağlayacağız.

[VB]

Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

    Dim Urunler As New List(Of Urun)

    Urunler.Add(New Urun With {.Adi = "Ürün Adi1", .Fiyat = 1000})

    Urunler.Add(New Urun With {.Adi = "Ürün Adi2", .Fiyat = 2000})

    Urunler.Add(New Urun With {.Adi = "Ürün Adi3", .Fiyat = 3000})

    Urunler.Add(New Urun With {.Adi = "Ürün Adi4", .Fiyat = 4000})

 

    comboboxUrunler.DisplayMemberPath = "Adi"

    comboboxUrunler.ItemsSource = Urunler

End Sub

[C#]

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            List<Urun> Urunler = new List<Urun>();

            Urunler.Add(new Urun { Adi = "Ürün Adi1", Fiyat = 1000 });

            Urunler.Add(new Urun { Adi = "Ürün Adi2", Fiyat = 2000 });

            Urunler.Add(new Urun { Adi = "Ürün Adi3", Fiyat = 3000 });

            Urunler.Add(new Urun { Adi = "Ürün Adi4", Fiyat = 4000 });

 

            comboboxUrunler.DisplayMemberPath = "Adi";

            comboboxUrunler.ItemsSource = Urunler;

        }

Combobox'ın ItemsSource özelliğine aktardığımız liste otomatik olarak Combobox'ın içerisine tüm öğelerin yerleştirilmesini sağlayacaktır fakat bizim yarattığımız Urun sınıfının hangi özelliğinin Combobox içerisinde gösterileceğini belirlememiz gerekiyor. Bunun için ComboBox'ın DisplayMemberPath özelliğine istediğimiz Urun sınıfının bir özelliğinin adını atıyoruz. Böylece ComboBox kendisine atanan dizideki her öğenin söz konusu özelliğindeki veriyi kullanıcıya gösterecektir.

Eğer veri bağlantısı sonrası ComboBox içerisinde seçili olacak öğeyi belirlemek isterseniz kullanabileceğiniz iki yöntem var.

[VB]

        comboboxUrunler.SelectedItem = (From gelenler In Urunler Where gelenler.Adi = "Ürün Adi2").SingleOrDefault

        comboboxUrunler.SelectedIndex = Urunler.IndexOf((From gelenler In Urunler Where gelenler.Adi = "Ürün Adi2").SingleOrDefault)

[C#]

comboboxUrunler.SelectedItem = (from gelenler in Urunler where gelenler.Adi == "Ürün Adi2" select gelenler).SingleOrDefault();

comboboxUrunler.SelectedIndex = Urunler.IndexOf((from gelenler in Urunler where gelenler.Adi == "Ürün Adi2" select gelenler).SingleOrDefault());

Bunlardan ilki doğrudan ComboBox'ın SelectedItem özelliğini tanımlayarak seçili öğeyi belirlemek. Yukarıdaki kod içerisinde elimizde diziden istediğimiz Item'ı bir LINQ sorgusu ile bularak söz konusu Item'ın SelectedItem olması gerektiğini belirlemiş oluyoruz. Bir diğer seçenek ise doğrudan seçili olacak Item'In Index numarasını SelectedIndex değerine aktarmak.

ComboBox içerisinde kullanıcı bir Item seçtiğinde ise doğrudan ComboBox'ın SelectionChanged event'ı çalıştırılacaktır. Böylece doğrudan SelectedItem özelliği üzerinden seçili öğeyi alabilir ve bu öğleyle ilgili bilgilere ulaşabilirsiniz. Bizim örneğimizde seçili öğenin tipinin de Urun olduğunu bildiğimiz için doğrudan Urun sınıfına Cast ederek seçili öğeye ait tüm bilgilere ulaşabiliyoruz.

[VB]

Private Sub comboboxUrunler_SelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles comboboxUrunler.SelectionChanged

    MessageBox.Show(CType(comboboxUrunler.SelectedItem, Urun).Fiyat)

End Sub

[C#]

        void comboboxUrunler_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            MessageBox.Show(((Urun)comboboxUrunler.SelectedItem).Fiyat.ToString());

        }

Hepinize kolay gelsin.

Thursday, October 02, 2008 2:43:27 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Silverlight 2.0  | 
 Wednesday, October 01, 2008

Silverlight 2.0 RC0 öncesinde Silverlight içerisinde özellikle kullanıcı girişlerinde şifrelerin yazılacağı bir TextBox oluşturmak epey zahmetli bir işti. Bunun için normal bir TextBox'ı sahneye yerleştiriyor sonra da bu TextBox'a tüm karakterleri * olan bir font bağlıyorduk. RC0 ile beraber artık bu işleme özgü bir PasswordBox kontrolümüz var. Bu yazımızda PasswordBox'ın kullanımına hızlıca değineceğiz.

Expression Blend 2 içerisinde PasswordBox kontrolü.
Expression Blend 2 içerisinde PasswordBox kontrolü.

Yeni bir Silverlight projesi yarattıktan sonra Expression Blend 2 içerisinde Asset Library bölümünde PasswordBox'ı bulabilirsiniz. Tasarım arayüzünden yukarıdaki şekilde bir PasswordBox alarak sahneye yerleştirdiğinizde XAML dosyasında aşağıdaki gibi bir kod ile karşılaşacaksınız.

<UserControl x:Class="SilverlightApplication4.Page"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="400" Height="300">

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

      <PasswordBox Height="25" Margin="28,38,136,0" VerticalAlignment="Top"/>

    </Grid>

</UserControl>

Kodumuzda PasswordBox bir Grid içerisinde bulunduğu için Margin'i ayarlanmış durumda. Bu şekilde hazırlanan basit bir uygulamayı çalıştırdığınızda PasswordBox içerisine girdiğiniz her karakter bir nokta ile gösterilecektir.

PasswordBox'ın varsayılan görünümü.
PasswordBox'ın varsayılan görünümü.

PasswordBox'ın noktalarla doldurduğu karakterlerin yerine farklı bir karakter seçmek için PasswordBox'ın PasswordChar özelliğinden faydalanabilirsiniz. Bu özelliğe aktardığınız karakter PasswordBox içerisine yazılan her karakterin gösteriminde kullanılacaktır.

<UserControl x:Class="SilverlightApplication4.Page"

            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

            Width="400"

            Height="300">

  <Grid x:Name="LayoutRoot"

        Background="White">

    <PasswordBox PasswordChar="*"

                Height="25"

                Margin="28,38,136,0"

                VerticalAlignment="Top"/>

  </Grid>

</UserControl>

Programatik olarak da yukarıda bahsettiğimiz tüm özelliklere VB veya C# kodunuz ile ulaşabilirsiniz.

Hepinize kolay gelsin.

Wednesday, October 01, 2008 1:32:52 PM (GTB Standard Time, UTC+02:00)  #    Comments [1]   Silverlight 2.0  | 
Copyright © 2010 Daron Yöndem. Tüm hakları saklıdır.