Makale Özeti

.NET Framework 3.0 ile beraber gelen WPF altyapısını kullanarak Expression Blend ile Windows uygulamaları tasarlarken kullanabileceğimiz zengin bir kontrol olan FlowDocumentReader kontrolünü incelediğimiz bu makalede ufak bir XAML Document Reader uygulaması hazırlayacağız.

Makale

WPF uygulamalarında kullanabileceğimiz farklı ve yepyeni windows kontrolleri var. Eski Windows uygulamalarından alıştığımız Button, Label vs kontrollerin yanı sıra çok kullanışlı ve ilginç kontroller mevcut. Bu kontrollerden özellikle FlowDocumentReader kontrolü çok hızlı bir şekilde işlevsel uygulamalar hazırlamanızı sağlayabilir. Gelin şimdi hemen Expression Blend ile bir WPF Windows Application yaratalım.

Yeni bir WPF Windows uygulaması yaratıyoruz.
Yeni bir WPF Windows uygulaması yaratıyoruz.

Uygulamamızı yarattıktan sonra içerisinde bir adet FlowDocumentReader kontrolü yerleştireceğiz. Bu kontrolü direk araç çubuğunda bulma şansınız yok. O nedenle araç çubuğundan "Asset Library" kısmına giderek kontrolümüzü orada bulmamız gerekecek.

FlowDocumentReader kontrolümüzü Asset Library içerisinde buluyoruz.
FlowDocumentReader kontrolümüzü Asset Library içerisinde buluyoruz.

Kontrolü uygulamamızdaki Window1 penceresine yerleştirdikten sonra kontrolümüze flowDoc adını vererek genişliğini ve yüksekliğini ayarlıyoruz. Son olarak da pencereye bir Button yerleştirerek içerisine de Content özelliğine "Doküman Aç" değerini vererek gerekli bilgiyi yazmış olduk. Window1.xaml dosyasının XAML kodları aşağıdaki şekilde sonuçlanıyor.

<Window

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

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

  x:Class="Window1"

  x:Name="Window"

  Title="Window1"

  Width="640" Height="480">

 

  <Grid x:Name="LayoutRoot">

    <FlowDocumentReader Margin="0,0,0,50" x:Name="flowDoc"/>

    <Button HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom" Width="136" Height="30" Content="Doküman Aç"/>

  </Grid>

</Window>


Programımızın tasarımını bitirdik. Sıra geldi kodlamaya. Penceremizdeki düğmeye basıldığında klasik Windows doküman açma dialoğunun gelmesini ve seçilen bir XAML dokümanını programımızda gösterilmesini istiyoruz. Burada özellikle bir detayı belirtmem gerek; programımızın açacağı XAML dosyaları FlowDocument formatında olmalı. Yani bunlar herhangi bir XAML dosyası olamaz. Bu dokümanların nasıl yaratılacağına ileride değineceğim ama şimdilik gelin örnek bir XAML dokümanını inceleyelim.

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

  <Table CellSpacing="5">

 

    <Table.Columns>

      <TableColumn/>

      <TableColumn/>

      <TableColumn/>

      <TableColumn/>

    </Table.Columns>

 

    <TableRowGroup>

 

      <TableRow Background="SkyBlue">

        <TableCell ColumnSpan="4" TextAlignment="Center">

          <Paragraph FontSize="24pt" FontWeight="Bold">Gezegen Bilgileri</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow Background="LightGoldenrodYellow">

        <TableCell>

          <Paragraph FontSize="14pt" FontWeight="Bold">Gezegen</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph FontSize="14pt" FontWeight="Bold">Güneşten Mesafe</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph FontSize="14pt" FontWeight="Bold">Çap</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph FontSize="14pt" FontWeight="Bold">Kütle</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow>

        <TableCell ColumnSpan="4">

          <Paragraph FontSize="14pt" FontWeight="Bold">İç Gezegenler</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow>

        <TableCell>

          <Paragraph>Merkür</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>57,910,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>4,880 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>3.30e23 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow Background="lightgray">

        <TableCell>

          <Paragraph>Venus</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>108,200,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>12,103.6 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>4.869e24 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow>

        <TableCell>

          <Paragraph>Dünya</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>149,600,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>12,756.3 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>5.972e24 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow Background="lightgray">

        <TableCell>

          <Paragraph>Mars</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>227,940,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>6,794 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>6.4219e23 kg</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow>

        <TableCell ColumnSpan="4">

          <Paragraph FontSize="14pt" FontWeight="Bold">Dış Gezegenler</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow>

        <TableCell>

          <Paragraph>Jupiter</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>778,330,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>142,984 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>1.900e27 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow Background="lightgray">

        <TableCell>

          <Paragraph>Satürn</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>1,429,400,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>120,536 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>5.68e26 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow>

        <TableCell>

          <Paragraph>Uranüs</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>2,870,990,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>51,118 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>8.683e25 kg</Paragraph>

        </TableCell>

      </TableRow>

      <TableRow Background="lightgray">

        <TableCell>

          <Paragraph>Neptün</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>4,504,000,000 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>49,532 km</Paragraph>

        </TableCell>

        <TableCell>

          <Paragraph>1.0247e26 kg</Paragraph>

        </TableCell>

      </TableRow>

 

      <TableRow>

        <TableCell ColumnSpan="4">

          <Paragraph FontSize="10pt" FontStyle="Italic">

            Kaynak:

            <Hyperlink NavigateUri="http://encarta.msn.com/encnet/refpages/artcenter.aspx">Encarta</Hyperlink>

            web sitesi.

          </Paragraph>

        </TableCell>

      </TableRow>

 

    </TableRowGroup>

  </Table>

</FlowDocument>


Bir FlowDocument'ın nasıl yaratılacağı ile ilgili detaylara girmeyeceğim. Ama sanırım yukarıda her şey yeterince açıktır. FlowDocument'ları Tag isimleri farklı birer HTML dokümanına benzetebilirsiniz. Programımız yukarıdaki şekilde düzenlenmiş belgeleri açabilecek.

Sıra geldi artık programlama kodumuzu yazmaya. Bunun için Expression Blend içerisinde düğmemizi seçerek sağ sütunda "Properties" sekmesine geçeceğiz. "Properties" sekmesi içerisinde de "Events" bölümüne geçtikten sonra "Click" özelliğine istediğimiz bir method adı yazacağız.

Düğmemizin Click durumuna ait methodu tanımlıyoruz.
Düğmemizin Click durumuna ait methodu tanımlıyoruz.

Yukarıdaki gibi DocAcTiklandi değerini yazdığınız Expression Blend size gerekli Event kodunuzu verecektir. Eğer bilgisayarınızda Visual Studio ve WPF Extension yüklü ise direk Visual Studio içerisinde projeniz açılacaktır. İlk baktığımızda aşağıdaki kodun otomatik olarak eklendiğini görüyoruz.

    Private Sub DokAcTiklandi(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

 

    End Sub


Programımızın Window1.xaml dosyasının XAML kodlarına baktığımızda ise ufak bir değişiklik görebiliriz.

<Window

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

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

  x:Class="Window1"

  x:Name="Window"

  Title="Window1"

  Width="640" Height="480">

 

  <Grid x:Name="LayoutRoot">

    <FlowDocumentReader Margin="0,0,0,50" x:Name="flowDoc"/>

    <Button HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom" Width="136" Height="30" Content="Doküman Aç" Click="DokAcTiklandi"/>

  </Grid>

</Window>


XAML kodlarına dikkatli olarak bakarsak artık Button nesnesine ait Click özelliğinin bizim için otomatik olarak ayarlanmış olduğunu görebiliriz. Bu noktadan sonra bizim tek yapmamız gereken uygun kodları Visual Studio içerisinde yazmak. İlk olarak aşağıdaki kod ile penceredeki FlowDocumentReader nesnesini bulacağım. Aslında buna normal şartlarda gerek yok, fakat bazen Visual Studio içerisinde Intellisense XAML kodundaki objeleri yakalayamıyor. Bunun nedeni büyük ihtimal ile tüm bu XAML desteğinin bir Extension olarak yükleniyor olması. Visual Studio 2008 ile yaptığım denemelerde böyle bir sorunla karşılaşmadım. O nedenle eğer siz de aynı sorunla karşılaşırsanız aşağıdaki kod ile kontrolümüzü yakalayabilirsiniz.

Dim flowDoc As FlowDocumentReader = CType(Me.FindName("flowDoc"), FlowDocumentReader)


Sonraki adımda ilk olarak kendimize özel bir FlowDocument nesnesi tanımlayacağız. Kullanıcının doküman açabilmesi için eski Windows uygulamalarında da kullandığımız OpenFileDialog nesnesinden yardım alacağız.

        Dim yeniDoc As Documents.FlowDocument = Nothing

        Dim Dialog As New Microsoft.Win32.OpenFileDialog

        Dialog.Filter = "FlowDocument Dosyaları (*.xaml)|*.xaml"

        If Dialog.ShowDialog.Value Then

 

        End If


Eğer OpenFileDialog ile kullanıcı bir dosya seçmiş ise sıra gelecek dosyayı okuyarak daha önce yarattığımız FlowDocument değişkenimiz olan yeniDoc değişkenine aktarmaya.

            Dim xamlDosya As FileStream = CType(Dialog.OpenFile, FileStream)

            Try

                yeniDoc = CType(Markup.XamlReader.Load(xamlDosya), Documents.FlowDocument)

                flowDoc.Document = yeniDoc

            Catch ex As Exception

                System.Windows.MessageBox.Show(ex.Message)

            End Try


Yukarıdaki kod içerisinde ilk satırda xamlDosya adında bir FileStream yaratarak dosyamızın konumunu alıyoruz. Sonrasında dosya okuma işlemini Try-Catch bloğu içerisinde gerçekleştireceğiz. En baştayarattığımız yeniDoc FlowDocument değişkenimize gerçek dosyayı okuyarak yüklemek için Markup.XamlReader sınıfını kullanıyoruz. Xaml dosyası okunduktan sonra değişken tipini de FlowDocument'a çevirerek kendi yeniDoc nesnemize aktardık. Artık elimizdeki FlowDocument değişkenimiz penceremizdeki FlowDocumentReader'a aktarılmaya hazır. FlowDocumentReader'a ait Document özelliğine gerekli değeri aktararak okuma işlemini sonlandırabiliriz. Tüm bu işlemler süresince eğer bir hata gerçekleşirse hatayı bir mesaj kutusu olarak Try-Catch bloğu ile kullanıcıya gösterebiliyoruz.

Artık programımızı deneyebiliriz. Visual Studio veya Expression Blend içerisinde F5'e bastığınızda program derlenecek ve otomatik olarak çalıştırılacaktır. Yukarıda örnek olarak verdiğimiz FlowDocument XAML dosyasını açtığımızda aşağıdaki gibi bir ekranla karşılaşıyoruz.

WPF uygulamamızda FlowDocumentReader görüntüsü.
WPF uygulamamızda FlowDocumentReader görüntüsü.

Gördüğünüz gibi dosyamız programımızda gösteriliyor. Peki neden FlowDocumentReader? FlowDocumentReader'ın özellikleri tek tek yazarak anlatmaya çalışmaktansa gelin aşağıda ufak bir seri görüntü ile durumu inceleyelim.

FlowDocument içerisinde otomatik sayfalama.
FlowDocument içerisinde otomatik sayfalama.

FlowDocumentReader kontrolünün kendi içerisinde bazı özellikleri var. Bunlardan ilki programın kullanıcısına açılan dokümanı farklı şekillerde okuyabilme olanağı sağlıyor olması. Yukarıdaki ekran görüntüsünde kullanıcı dokümanı sayfalar şeklinde görmek istediği için FlowDocumentReader gerekli düzenlemeleri otomatik olarak yapmış. Tüm bu işlemlerin tamamen vektörel olarak yapıldığını bu nedenle her şekilde yazılarda ve grafiklerde çok net görüntüler alındığını özellikle belirtmek istiyoruz.

FlowDocumentReader'da zoom yapmak arama yapmak kadar kolay.
FlowDocumentReader'da zoom yapmak arama yapmak kadar kolay.

FlowDocumentReader kontrolü ile beraber gelen diğer özellikler de çok etkileyici. Kullanıcı istediği zaman dokümana zoom yapabiliyor. Yukarıdaki görüntüde dokümanın biraz büyütülmüş halini görebilirsiniz. Yazılarda herhangi bir bozulma yok. Aynı şekilde kullanıcı isterse yazıların boyutu FlowDocumentReader'ın sağ altında bulunan kontroller ile küçültebilir de. Son olarak bahsetmek istediğim belki de en önemli işlevlerden biri de Arama. FlowDocumentReader ile beraber otomatik bir arama motoru geliyor ve açılan doküman içerisinde aramaları FlowDocumentReader tamamen kendisi yapıyor.

Sanırım artık neden bu yazımda FlowDocumentReader'ı anlatmak istediğimizi anlamışsınızdır. Tabiri caiz ise iki satır kod yazarak muhteşem bir program yapmış olduk. WPF olmadan önce bu tarz bir programı hazırlamak belki de bir haftamızı alırdı.

FlowDocument Dosyaları nasıl yaratılır?

Gelelim can alıcı soruya. Eminim ki çoğunuz şu anda elinizdeki bir sürü dokümanı yukarıdaki şekilde windows uygulamaları ile göstermek müşterilerinize projelerde göstermek istiyorsunuz. Daha önce de bahsettiğim gibi HTML ile FlowDocument yazımı arasında ciddi benzerlikler var. Bu noktada HTML'den FlowDocument'a yani XAML'e çevirmek için gerekli araçlar da hazır. Aşağıdaki adresten XAML'den HTML'e veya tam tersi HTML'den XAML'e çeviri yapabilen bir yazılımı açık kaynak kodu ile indirebilirsiniz.

http://wpf.netfx3.com/files/folders/developer/entry816.aspx

Hepinize kolay gelsin.

Daron Yöndem
MCT, MCPD, MCITP, MCTS, MCSD,
MCAD MCDBA, MCP, ACP, ICSD, IEL'03
http://daron.yondem.com 

Makale boyunca yaptığımız örneğin kaynak kodlarını indirebilirsiniz.