C# 3.0 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
C# 3.0 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Cumartesi, Ağustos 15, 2009

Ado.Net Entity Framework – Entity Model ile Windows Form Uygulamaları ve Bug

Veri tabanı ile ilişkisel olarak yapmış olduğumuz işlemleri Ado.Net Entity Framework ile yaptığımızda çok daha hızlı ve kolay bir şekilde yapabilinmesi mümkündür. Ne kadar basit yapılabileceğine ilişkin basit bir örnek verelim.

Visual Studio 2008 ile Windows From projesi oluşturuyor ve sonrasında entity data model template ‘ini projeye ekliyoruz. edmx ‘in içerisine gerekli olan tabloları ekledikten sonra işlemleri yapmaya başlayabiliriz.

Windows Formun üzerine aşadağıdaki kontrolleri ekliyoruz.

Windows Form

Tasarımı oluşturduktan sonra aşağıdaki kodları ekliyoruz.

using System;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;

namespace CourseManager
{
    public partial class CourseViewer : Form
    {
        public CourseViewer()
        {
            InitializeComponent();
        }
        private SchoolEntities schoolContext;
        private void closeForm_Click(object sender, EventArgs e)
        {
            schoolContext.Dispose();
            this.Close();
        }

        private void CourseViewer_Load(object sender, EventArgs e)
        {
            schoolContext = new SchoolEntities();
            ObjectQuery<Department> departmentQuery = schoolContext.Department.Include("Course").OrderBy("it.Name");
            try
            {
                this.departmentList.DisplayMember = "Name";
                this.departmentList.DataSource = departmentQuery;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void departmentList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                Department department = (Department)this.departmentList.SelectedItem;
                courseGridView.DataSource = department.Course;
                courseGridView.Columns["Department"].Visible = false;
                courseGridView.Columns["CourseGrade"].Visible = false;
                courseGridView.Columns["OnlineCourse"].Visible = false;
                courseGridView.Columns["OnSiteCourse"].Visible = false;
                courseGridView.Columns["Person"].Visible = false;

                courseGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void saveChanges_Click(object sender, EventArgs e)
        {
            try
            {
                schoolContext.SaveChanges();
                MessageBox.Show("Changes saved to the database");
                this.Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Yukarıdaki kod bloglarını da projeye ekledikten sonra projemizi çalıştırdığımız aşağıdaki gibi bir görünüme sahip olacağız.

Debugging Windows Form

Evet herşey güzel gözüküyor.

Peki, bug nerede?

            {
                Department department = (Department)this.departmentList.SelectedItem;
                courseGridView.DataSource = department.Course;
                courseGridView.Columns["Department"].Visible = false;
                courseGridView.Columns["CourseGrade"].Visible = false;
                courseGridView.Columns["OnlineCourse"].Visible = false;
                courseGridView.Columns["OnSiteCourse"].Visible = false;
                courseGridView.Columns["Person"].Visible = false;

                courseGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
            }
Veri tabanında yer alan tabloların gözükmemesi için görünebilirliğini pasif yapıyoruz. Ancak bu işlem esnasında yanlışlıkla CourseGrade yerine CourseGrades yazdım ve karşımıza aşağıdaki gibi bir sonuç çıkmıştır.

EntityBug

Dikkat ederseniz yanlış yazdığımız bölüm sonrası kapatmış olduğumuz bütün tablo isimleri gözükmüştür.

Ancak her ne olursa olsun Entity Framework ‘ün uygulamalarımıza kattıkları oldukça fazladır. Bu tür Bug ‘lar da .Net Framework ‘ün tamamlanması ile büyük ihtimal ortadan kalkacaktır.

Eğer ki sizler de bu tür buglar keşkefederseniz www.connect.microsoft.com adresinden hata merkezine belirtebilirsiniz.

Umarım yararlı olabilmiştir.

Perşembe, Temmuz 23, 2009

VSTO 2008 - Genel Özellikler ve Outlook 2007 için Form Uygulaması Oluşturulması

Microsoft 'un en çok beğenilen uygulamalarından biri olan Office System 2007 bile bazen ihtiyaçlarımıza cevap veremeyebilir. İşte bu noktada ne yapmalıyız sorusunu kendimize sormaya başlarız. Bu noktada yapmış olduğumuz araştırmalar sonrasında da Visual Studio 2008 ile Office uygulamalarına Add-in yazılabileceğimizi öğreniriz. Peki bu işlemi nasıl gerçekleştirebiliriz ve hangi uygulamaların bilgisayarımızda kurulu olması gerekmektedir.

Gerekli olan uygulamalar:
1.)
Visual Studio 2008
2.) Office System 2007
3.) Windows XP veya üstü bir işletim sistemi

Yukarıda saymış olduğumuz uygulamaları bilgisayara kurduktan sonra artık Office Add-in yardımı ile çalışabilir duruma geliyoruz. Bu eklentileri Visual Studio 2008 ile hazırladığımızda adlandırılma olarak VSTO 2008 olmaktadır.

İşlemleri nasıl yapacağımızı bir örnek üzerinde değerlendirelim. Örnek olarak Outlook 2007 kontaklarını resim olarak listeleyen ve üzerene tıkladığımızda da bize o kişinin kontak detaylarını getirecek. Şimdi adım adım nasıl yapacağımızı incelemeye çalışalım.

İlk yapılması gereken Visual Studio 2008 üzerinde proje oluşturulması olacaktır. Bu işlem için proje şablonları arasından Outlook 2007 Add-in projesini seçeceğiz ve sonrasında karşımıza gelen ekrandan Outlook 2007 Add-in projesini seçtikten sonra geliştirmeye başlayabilir duruma geliyoruz.



Proje şablonunu oluşturduktan sonra ThisAddin isimli sınıf oluşmaktadır. Bu sınıfın ana amacı oluşturulan Add-in açıldığından ve kapatıldığında ne iş yapılacağını açıklamaktadır. Fakat unutulmaması gereken bir nokta var ki o da, oluşturmak istediğimiz Add-in 'nin Outlook ta herhangi bir formun içerisinde mi açılacağı yoksa Outlook ile birlikte mi çalışacağıdır. Biz uygulamamız esnasında içte açılan bir yöntemi tercih edip işlemlerimize devam edelim.

Not: Outlook dışı çalışmasını istiyorsak yapmamız gereken Add->New Item seçeneğinden Windows form ya da WPF Form 'ı ekledikten sonra işlemleri yapmak olacaktır...

ThisAddin sınıfının içerisinde neler varmış bir göz atmak gerekirse,

ThisAddin.cs
namespace Contacts
{
    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }
}

Daha önceden de değindiğimiz üzere ThisAddin sınıfının içerisinde Add-in başladığı ve sonlandığı anda yer alan olaylar yer almaktadır. Outlook içerisinde kontaklar menüsünde uyumlu bir şekilde çalışacak olan içeriğini oluşturmaya başlayalım.

Uygulamanın üzerinde sağ tıklama yaptıktan sonra Add->NewItem adımlarını izliyor ve karşımıza çıkan ekrandan Office tabının içerisinde yer alan Outlook Form Region form şablonunu ekle diyerek işlemlerimize devam ediyoruz.



Ayrıca yukarıdaki ekrandan göreceğiniz üzere Ribbon yer alan formlarda hazırlayabilmemiz mümkündür. Bu kullanım şeklini de zaman içerisinde incelemeye çalışacağız. Seçeneği seçtikten ve ekle dedikten sonra karşımıza çıkan ekranda yeni bir Outlook Form mu tasarlayacağımızı yoksa var olan bir formdan mı yararlanacağımızı sormaktadır.



Yukarıda karşımıza çıkan seçenekten Design a new form region seçeneğini seçerek devam ediyoruz. Bir sonraki ekranda karşımıza ekleyecek olduğumuz formun ekran üzerinde nasıl yer alacağına ilişkin bilgiler girmemizi istemektedir.



Bu adımda Outlook ekranında Ribbon altında yer alan alanın hepsini dolduracak olan ve Ribbon içerisinde yeni bir ek yapacak olan Separate seçeneğini seçeceğiz. Diğer seçeneklerin ne işe yaradığını açıklamak gerekirse,

*Adjoining: Form 'u çalışma alanın alt kısmında tutar ve Add-in 'i var olan bir menü içerisine ekleme yapar.
*Replacement: Varsayılan form alanının içerisine ekleme yapar ve Add-in 'i var olan bir menü içerisine ekleme yapar.
*Replace-All:  Ribbon menüyü bizim istediğimiz şekilde yapılandırır ve Add-in 'i var olan bir menü içerisine ekleme yapar.

Separete seçeneğini tıkladıktan sonra bir sonraki adıma geçiş yapıyoruz. Bu ekranda bizden ekleyecek olduğumuz Add-in görünecek adını, üzerine fare ile tutulduğunda ne gibi bir açıklama vereceğini, açıklamasını ve kullanım alanının içinde nasıl çalışacağını ilişkin bilgiler girmemizi istemektedir.



Form Region 'a ilişkin bilgileri de girdikten sonra bir sonraki adımımızda işlemimizi var olan bir sınıf üzerinde mi yapacağız yoksa biz harici sınıf mı oluşturacağız diye sormaktadır. Yazının başından da hatırlayacağınız üzere örneğimizi kontaklar (Contact) üzerine yapacaktık. Bu durumda karşımıza çıkan ekrandan IPM.Contact seçeneğini seçmek isteklerimizi karşılayacak bir çözüm olacaktır.



Evet artık VSTO (Visual Studio Tools for Office) ile Add-in 'ni boş form ile oluşturmuş oluyoruz. Otomatik hazırlanın formun içerisinde FormRegionClosed ve FormRegionShowing olaylarını incelersek arka planda FormRegionMyContacts sınıfının içerisinde yer alan  kod bloklarına götürdüğünü göreceksiniz.

FormRegionMyContacts.cs
namespace Contacts
{
    partial class FormRegionMyContacts
    {
        #region Form Region Factory

        [Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Contact)]
        [Microsoft.Office.Tools.Outlook.FormRegionName("Contacts.FormRegionMyContacts")]
        public partial class FormRegionMyContactsFactory
        {
            // Occurs before the form region is initialized.
            // To prevent the form region from appearing, set e.Cancel to true.
            // Use e.OutlookItem to get a reference to the current Outlook item.
            private void FormRegionMyContactsFactory_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
            {
            }
        }

        #endregion

        // Occurs before the form region is displayed.
        // Use this.OutlookItem to get a reference to the current Outlook item.
        // Use this.OutlookFormRegion to get a reference to the form region.
        private void FormRegionMyContacts_FormRegionShowing(object sender, System.EventArgs e)
        {
        }

        // Occurs when the form region is closed.
        // Use this.OutlookItem to get a reference to the current Outlook item.
        // Use this.OutlookFormRegion to get a reference to the form region.
        private void FormRegionMyContacts_FormRegionClosed(object sender, System.EventArgs e)
        {
        }
    }
}

Şimdi uygulamamız üzerinde herhangi bir değişiklikte bulunmadığımız haliyle çalıştıralım ve Outlook içerisinde nasıl bir görünüm alacağına göz atalım. Oluşturulmuş olan proje derlendiğinde Outlook 'un otomatik olarak açılacak ve geliştiricinin gerekli testleri yapması için beklemeye başlayacaktır. Daha sonra derleme işlemi sonlandırıldığında Outlook uygulaması da kendisini otomatik olarak kapatacaktır. Biz uygulamamızı kontaklar içerisine eklenmesini istemiştik. Bakalım istediğimiz gerçekleşmiş mi?



Oldukça başarılı... İstediğimiz sonucu almışa benziyoruz. Peki biz bu Add-in 'nin üzerine tıkladığımızda karşımıza nasıl bir form görüntüsü gelecek. Tabii ki boş. Çünkü hiç bir düzenleme işlemi yapmamıştık. Şimdi ise eklemiş olduğumuz Add-in 'i nasıl geliştirebileceğimizi incelemeye çalışalım.

Örneğimizde aynı kategori içerisinde yer alan tüm kişileri göstermek istiyoruz. Yazımızın başında da bahsettiğimiz üzere kontak listemizin hepsini sadece resimleri ile göstermek istiyoruz. bu işlemi gerçekleştirebilmek için OutlookItem nesnesini kullanmamız gerekmektedir. Eriştiğimiz Outlook öğesinin alt özelliklerinde ContactItem 'a erişeceğiz ve bütün kontakları sorunsuzca kullanıcılara getirebileceğiz. Eğer kontaklarımızda kategori uygulanmış ise biz kişileri gösterirken bu kategoriye de göz önüne alarak bir işlem yapmamız gerekmektedir. Bu işlem için string filtre uygulamak mantıklı bir işlem olacaktır. Örneğin Outlook kontakları içerisinde yer alan arkadaşlar grubuna ilişkin kayıtları göstermek istiyorum. Bu noktada yapılması gereken bir ListView içerisine Contact nesnesinin içerisinde yer alan resim özelliklerini bu kontrolde doldurmak olacaktır. Genel olarak istediklerimizi açıkladığımıza göre işlemlerimizi yapmaya devam edebiliriz.

İlk olarak filtre hazırlama işlemini nasıl gerçekleştireceğimize göz atalım.

FormRegionMyContacts.cs
/// <summary>
/// Filtreleme işlemi için yapıldı.
/// </summary>
/// <param name="messageClass">İstenen mesaj sınıfı</param>
/// <param name="categoryList">kontaklar için kategori listesi</param>
/// <returns></returns>
string BuildSQLFilter(string messageClass, string[] categoryList)
{
    //StringBuilder nesnesinin kullanıyoruz.
    StringBuilder filter = new StringBuilder(250);
    //SQL Prefix (Ön eki)
    filter.Append(@"@SQL(");
    //MessageClass yardımı ile duruma özel mesaj verdirir.
    filter.Append(string.Format(@"(""http://schemas.microsoft.com/mapi/proptag/0x001a001e"" = '{0}')",
                        messageClass));
    //Kategori var mı diye kontrol eder ve sonrasında AND koşulunu uygular.
    if (categoryList.Length > 0) filter.Append("AND(");
    //Kategori var mı diye kontrol eder ve sonrasında AND koşulunu uygular.
    for (int index = 0; index < categoryList.Length; index++)
    {
        if (index > 0) filter.Append("OR");
        filter.Append(string.Format(@"(""urn:schemas-microsoft-com:office:office#Keywords"" LIKE '%{0}%')",
                                                    categoryList[index].Trim()));

    }
    //AND blogunun sonu
    if (categoryList.Length > 0) filter.Append(")");
    //SQL blogunun sonu
    filter.Append(")");
    return filter.ToString();
}

Kontaklar içerisinde yer alan kategorilerden isteğimize erişebilir ve içinde yer alan kayıtları görebilir duruma gelmiş bulunuyoruz. Şimdi ise filtre sonucunda gelecek olan kontakları yavaş yavaş göstermeye başlayalım. Outlook dosyaları Outlook.MAPIFolder içerisinde tutmaktadır. Bu durumda dosyalara erişmek istediğimizde bu nesneyi kullanmamız gerekecek. Ayrıca ListView için tablo kullanmak gerekecek. Outlook.Table nesnesini kullanarak bu işlemi de gerçekleştirebilmemiz mümkündür. Ayrıca dikkat etmemiz gereken bir nokta var. Biz bu işlemleri yaparken arka planda çalışmasını sağlayacak bir yapıda kurmamız gerekmektedir. Bu işlemi de uygulamamız esnasında hazırlıyor olmamız gerekmektedir.

Kontaklara eriştikten sonra verilere ulaşmak için kullandığımız yöntem aşağıdaki gibi olacaktır.

FormRegionMyContacts.cs
private readonly Size _imagesize = new Size(50, 75);

// Occurs before the form region is displayed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegionMyContacts_FormRegionShowing(object sender, System.EventArgs e)
{
    Outlook.ContactItem contact;
    Outlook.MAPIFolder folder;
    Outlook.Table table;
    try
    {
        //Outlook ContactItem 'dan değerleri getiriyor...
        contact = this.OutlookItem as Outlook.ContactItem;
        //kontak klasörünü nesne olarak getirir.
        folder = contact.Parent as Outlook.MAPIFolder;

        //kontakları kategorilere göre getirir.
        string categories = contact.Categories ?? string.Empty;
        string[] categoryList = categories.Split(';');

        //Hazırlanmış olan SQL filtre metoduna göre gerekli işlemler gerçekleştiriliyor.
        string filter = BuildSQLFilter("IPM.Contacy", categoryList);
        //filtrelenmiş değerleri tabloya dolduruyoruz.
        table = folder.GetTable(filter.ToString(), Outlook.OlTableContents.olUserItems);
        //Gelen değerleri tablo içerisine kolonlara doldurulur.
        table.Columns.RemoveAll();
        table.Columns.Add("EntryID");
        table.Columns.Add("FileAs");
        table.Columns.Add(@"urn:schemas:contacts:profession");
        table.Columns.Add("Email1Address");
        table.Columns.Add(@"urn:schemas:contacts:businesshomepage");
        table.Columns.Add(
                    @"http://schemas.microsoft.com/mapi/id/{00062004-0000-0000-C000-000000000046}/8062001F");
        table.Columns.Add("Categories");
        // MAPI özelliklerinden resim değerlerini nasıl alacağını göstereceğiz.
        table.Columns.Add(
                    @"http://schemas.microsoft.com/mapi/id/{04200600-0000-0000-C000-000000000046}/8015000B");
        // resim listesi oluşturma ve Resim yok görüntüsnün eklenmesi
        ImageList imageList = new ImageList();
        imageList.ImageSize = _imagesize;
        imageList.ColorDepth = ColorDepth.Depth24Bit;
        //resim listesinde resim yoksa listview üzerinde yer alan resimler resim yok görüntüsünün gözükmesi
        listviewContacts.LargeImageList = imageList;
        imageList.Images.Add(string.Empty, Properties.Resource.NoPicture);

        //Kontaklar ListView 'ın içerisine resimleri ile birlikte dolduruluyor...
        List<string> contactsWithPicture = new List<string>();

        //Outlook kontaklarında Business Card olarak girilmiş olan bilgilerde yer alan
        //resimlerin görütülenmesini sağlamaktadır.
        while (!table.EndOfTable)
        {
            Outlook.Row row = table.GetNextRow();
            //satır bilgileri dolduruluyor.
            ContactInfo info = new ContactInfo(row);
            if (info.HasPicture)
            {
                contactsWithPicture.Add(info.EntryId);
            }
            if (contact.EntryID != info.EntryId)
            {
                ListViewItem listViewItem = this.listviewContacts.Items.Add(info.FileAs, 0);
                listViewItem.Tag = info;
                listViewItem.Name = info.EntryId;
                listViewItem.ToolTipText = info.EmailAddress;
            }
            else
            {
                UpdateBusinessCard(info, GetContactPicture(info.EntryId));
            }

            //uzun süren çalışmaların için arka planda çalışabilme özelliği
            _backgroundWorker = new BackgroundWorker();
            _backgroundWorker.WorkerSupportsCancellation = true;
            _backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
            _backgroundWorker.RunWorkerAsync(contactsWithPicture);
        }
    }
    finally
    {
        table = null;
        folder = null;
        contact = null;
    }
}

Şimdiye kadar kontaklara ilişkin verileri getirecek ve resim yoksa görüntü yok ekranını gösterecek, ayrıca çok fazla veri gelecekse bu çalışmayı ekran yüklenirken değil de arka planda çalışabilmesine olanak verecek yapının hazırlanması için temel adımları gerçekleştirmiş bulunuyoruz. Şimdi ise yukarıdaki kod bloğunda kullanmış olduğumuz metotların ve event ların içeriklerini doldurma işlemini gerçekleştirelim. Bu amaçla yapacağımız ilk işlem BusinessCard kontak tipini eklenen resimlerin ListView içerisinde gözükmesi olacaktır.

FormRegionMyContacts.cs
private Image GetContactPicture(string entryID)
{
    var contact =
        Globals.ThisAddIn.Application.Session.GetItemFromID(entryID, null) as Outlook.ContactItem;
    Image img = null;
    string tempPath = Environment.GetEnvironmentVariable("TEMP");
    if (contact != null)
    {
        foreach (Outlook.Attachment attachment in contact.Attachments)
        {
            if (attachment.FileName == "ContactPictıre.jpg")
            {
                string fileName = Path.Combine(tempPath, entryID + ".jpg");
                attachment.SaveAsFile(fileName);
                FileStream stream = new FileStream(fileName, FileMode.Open);
                Bitmap bmp = new Bitmap(Image.FromStream(stream, true));
                if (bmp.Width > bmp.Height)
                {
                    Bitmap tempBmp = new Bitmap(_imagesize.Width, _imagesize.Height);
                    Graphics g = Graphics.FromImage(tempBmp);
                    g.FillRectangle(Brushes.White, 0, 0, _imagesize.Width, _imagesize.Height);
   
                    float ratio = (float)bmp.Height / bmp.Width;
                    int newHeight = (int)(ratio * bmp.Height);
                    int top = (_imagesize.Height - newHeight) / 2;
                    g.DrawImage(bmp, new Rectangle(0, top, _imagesize.Width, _imagesize.Height));
                    img = tempBmp;
                    g.Dispose();
                }
                else
                {
                    img = new Bitmap(bmp, _imagesize);
                }
                    stream.Dispose();
                    File.Delete(fileName);
                    break;
            }
        }
    }
    contact = null;
    return img;
}

Arka plan çalışma işlemlerinin detaylarını girelim şimdi de. İlk olarak resimlerin çalışma prensipleri ile alakalı işlem yapmamız gerekmektedir. Hatırlayacağınız üzere BusinessCard görünümünde yer alan resimleri EntryId 'lerinden yararlanarak resimlerini göstereceğimizden bahsetmiştik. Şimdi bu işlemi gerçekleyecek olan kod bloğunu ekleyelim.

FormRegionMyContacts.cs
private void listViewContacts_DoubleClick(object sender, EventArgs e)
{
    Point position = listViewContacts.PointToClient(Control.MousePosition);
    ListViewItem listViewItem =
    listViewContacts.GetItemAt(position.X, position.Y);
    if (listViewItem == null) return;

    OpenItem(listViewItem.Name);
}

private void OpenItem(string entryId)
{
    Outlook.ContactItem contact = Globals.ThisAddIn.Application.Session.GetItemFromID(entryId, null) as Outlook.ContactItem;
    contact.Display(false);
    contact = null;
}

private void listViewContacts_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
{
    UpdateBusinessCard((ContactInfo)e.Item.Tag, listViewContacts.LargeImageList.Images[e.Item.ImageIndex]);
}

Metotlarımızı hazırlarken çok sık olarak ContactInfo sınıfını oluşturalım. Bu sınıf içerisinde BusinessCard içerisinde yer alan iletişim bilgilerine ilişkin elemanlar yer almaktadır.

ContactInfo.cs
namespace Contacts
{

public class ContactInfo
{

    /// <summary>
    /// Outlook satır ve sütunlarında yer alan bilgiler için kullanırlar
    /// </summary>
    /// <param name="row"></param>
    public ContactInfo(Microsoft.Office.Interop.Outlook.Row row)
    {
        EntryId = (string)row[1];
        FileAs = (string)row[2];
        JobTitle = (string)(row[3] ?? string.Empty);
        EmailAddress = (string)(row[4] ?? string.Empty);
        Homepage = (string)(row[5] ?? string.Empty);
        MessengerAddress = (string)(row[6] ?? string.Empty);
        string categories = (string)(row[7] ?? string.Empty);
        Categories = categories.Split(';');
        HasPicture = (bool)(row[8] ?? false);
    }

    public string EntryId { get; private set; }
    public string FileAs { get; private set; }
    public string JobTitle { get; private set; }
    public string EmailAddress { get; private set; }
    public string Homepage { get; private set; }
    public string MessengerAddress { get; private set; }
    public string[] Categories { get; private set; }
    public bool HasPicture { get; private set; }
    }
}

Sürekli olarak kod tarafında neler yapacağımıza göz attık. Peki bu hazırlamış olduğumuz tasarımın tasarım ekranı nasıldır?



Tasarım tarafında keyfimize istediğimiz .Net kontrolünü kullanabilmemiz mümkündür. Sıra kontak bilgilerinin gösterilmesine geldi. Son kullanıcı resmin üzerine çift tıklama ya da başka bir işlem yaptığında kontak eklediği ekran açılarak değişiklik yapabilmesine olanak tanıyacağız.

FormBusinessCard.cs
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Office.Interop.Outlook;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Contacts {
    public partial class FormBusinessCard : UserControl {


        public FormBusinessCard() {
            InitializeComponent();
        }

        /// <summary>
        /// BusinessCard dan bilgileri alarak doldurur
        /// </summary>
        /// <param name="info">ContactInfo nesnesi.</param>
        /// <param name="image" >Kontakın resmi</param>
        public void SetContactInfo( ContactInfo info , Image image){
            EntryId = info.EntryId;
            LastFirst.Text = info.FileAs;
            Profession.Text = info.JobTitle;
            Emailaddress.Text = info.EmailAddress;
            Messenger.Text = info.MessengerAddress;
            Homepage.Text = info.Homepage;
            Categories.Text = string.Join("\n", info.Categories);
            Image.Image = image;
        }


        /// <summary>
        /// Outlook ContactItem 'dan EntryId 'yi getirir
        /// </summary>
        public string EntryId { get; set; }
       
        /// <summary>
        /// BusinessCarda çitt tıkladığında olacak işlemler uygulanır.
        /// </summary>
        private void FormBusinessCard_MouseDoubleClick(object sender, MouseEventArgs e) {
            OpenItem(EntryId);
        }

        /// <summary>
        /// Detayları ile kişinin kontak bilgilerini getirir.
        /// </summary>
        /// <param name="entryId">Kontağın entryId 'si</param>
        void OpenItem(string entryId) {
            Outlook.ContactItem contact = Globals.ThisAddIn.Application.Session.GetItemFromID (entryId , null) as Outlook.ContactItem ;
            contact.Display(false);
            contact = null;
        }

        /// <summary>
        /// Ana ekrana link veren link clicked
        /// </summary>
        private void Homepage_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            ShowHomePageInBrowser(Homepage.Text);
        }

        void ShowHomePageInBrowser(string url){
            Process p = new Process();
            p.StartInfo.FileName = "IExplore.exe";
            p.StartInfo.Arguments = url;
            p.Start();
        }

        /// <summary>
        /// Live messenger 'a tıklandığında kontak ile chat penceresinde konuşulabilmesini sağlar
        /// </summary>
        private void Messenger_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            ConnectToMessenger(Messenger.Text);
        }

        /// <summary>
        /// Email adresini kullanarak anlık mesajlaşma (messenger) penceresi açar.
        /// </summary>
        /// <param name="email">the emailaddress of the partner</param>
        void ConnectToMessenger(string email) {
            try{
                // Messenger oluşturuluyor.
                Type messengerType = Type.GetTypeFromProgID ("Messenger.UIAutomation.1");
                object comObject = Activator.CreateInstance (messengerType);
   
                // e-mail adreslerine göre kişiler konuşma penceresine davet ediliyor.
                object[] arguments = new object[] { email };
                messengerType.InvokeMember ("InstantMessage", BindingFlags.InvokeMethod,null, comObject, arguments);
                Marshal.ReleaseComObject(comObject);


                } catch(System.Exception ex){
                    MessageBox.Show("Please make sure you have installed the latest Windows Messenger Live and that you are signed-in." );
            }
        }

        private void Emailaddress_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
            SendEmail(LastFirst.Text, Emailaddress.Text);
        }

        /// <summary>
        /// mail adresi oluşturulması isteniyor.
        /// </summary>
        /// <param name="emailAddress">kontakların mail adresleri</param>
        void SendEmail(string name,string emailAddress) {
            Outlook.MailItem mail = Globals.ThisAddIn.Application.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Outlook.MailItem ;
            mail.Recipients.Add (string.Format("{0}<{1}>", name, emailAddress ));
            mail.To = emailAddress;
            mail.Display(false);
            mail = null;
        }
    }
}

Evet artık geliştirme süreçlerimizi tamamlamış oluyoruz. Sıra test yapmaya geldi. Test için yapmamız gereken uygulamamızı çalıştırmak olacaktır. Çalışma esnasında Outlook 2007 (Outlook 2010 üzerinde de sorunsuzca çalışmaktadır.) uygulaması açılacak ve eklemiş olduğumuz Add-in bizim kullanımımız için hazır durumda bulunacaktır.



Uygulamamız sorunsuz bir şekilde çalıştı ve isteklerimizi yapar duruma gelmiştir.

Yazımızı sonlandırmadan önce bu yapmış olduğumuz Add-in 'i son kullanıcıların bilgisayarlarına kurmak istediğimiz ne tür işlemler uygulamamız gerektiğine değinelim. Yazımızın içerisinde de bahsettiğimiz üzere VSTO == Visual Studio Tools for Office 'tir. Bu uygulama tipi ile hazırlanmış örnekler ise *.vsto uzantısı ile oluşturulmaktadır. Eğer ki bilgisayarlarda Visual Studio 2008 kurulu değilse bilgisayarlar vsto uzantısını tanımayacaktır. Bu durumda yapmamız gereken Microsoft Visual Studio Tools for the Microsoft Office System Runtime uygulamasını bilgisayarlara kurmak olacaktır. Sonrasında bilgisayarlar VSTO uzantısını algılayacak ve kurulum işlemini gerçekleştirecektir.

Kurumlar içerisinde çalışan geliştiriciler için en büyük sorun ise bilgisayarlara herhangi bir uygulama kurulmasına izin verilmemesinden kaynaklanmaktadır. Bu uygulama kurulurken ne yapmamız gerekmektedir peki. Bilgisayarlara ilk olarak Admin kullanıcı ile VSTO Runtime 'ı kurmamız gerekmektedir. Sonrasında ise oluşturmuş olduğumuz uygulamayı kurmak istediğimizde herhangi güvenlik engeline takılmadan kurabilmemize olanak tanınacaktır. Peki Runtime kurulurken admin kullanıcısı hakkı isterken neden uygulama kurulurken böyle bir istekte bulunmamaktadır. Çünkü VSTO uygulamaları çalışacakları Office uygulamasını doğrular ve sonrasını kendisini ekler. Yani kurmaz. Bu sebepten ötürüde kurulum esnasında herhangi bir güvenlik kontrolüne takılmayacaktır.

SoSonuç olarak Visual Studio üzerinde VSTO 2008 uygulamasını ne için oluşturacağımızda nasıl oluşturacağımıza kadar örnek üzerinde incelemeye çalıştık. Sonrasında ise geliştirmiş olduğumuz uygulamanın son kullanıcıların bilgisayarlarına nasıl kurulacağını hem kurum bazında hem de küçük işletmeler bazında değinmeye çalıştık.

Uygulamanın kaynak kodlarına buradan erişebilmeniz mümkündür.

Umarım yararlı olabilmiştir.

Turhal Temizer

info@turhaltemizer.com

Çarşamba, Temmuz 15, 2009

Asp.Net MVC Framework - Validation İşlemleri - I

Asp.Net ile geliştirdiğimiz uygulamalarda kullanıcı bazlı olarak işlem yaptırmak istediğimizde verilen doğru olarak girilip girilmediğini kontrol etmemiz gerekmektedir. Örneğin böyle bir kontrol yapmadığımızda kişiler kimlik numarasını girmek yerine adını da yazabilmektedir. Bu istenmeyen bir durumdur. Kimlik numarası 11 haneden oluşmakta ve yalnızca rakamlardan oluşmaktadır ki harf girilmesi istenmeyen durumlar arasında gösterilmektedir. Peki bu kontrolü yapmak için nasıl işlemler uygulamamız gerekmekte kısaca bir hatırlayalım. Klasik yöntemlerden birincisi sayfamızın markup kod tarafında Java Script ile hazırlanmış kontrolleri ekleyerek kullanabiliriz. Bir diğer seçeneğimiz *.cs veya *.vb kod tarafında hazırlamış olduğumuz manüel kontroller yardımı ile bu durumu engelleyebilme şansımız vardır. Fakat bu yöntemin çalışması için internet sayfasının en az bir kez server ile haberleşmesi ve yeniden yüklenmesi gerekmektedir ki bu da web sitesinin hızlılığı açısından istenmeyen bir durumdur. Son ve en sık kullanılan özellik ise Asp.Net Validation kontrollerinin kullanılmasıdır. Bu yöntem oldukça başarılı ve bizim kullanmış olduğumuz kontrol üzerindeki işlemimiz tamamlandığı anda kendisini aktifleştiren bir yöntemdir.

Yukarıdaki paragrafta yer alan özelliklerin hepsini okuduktan sonra her şey çok güzel o zaman ben işlemimi Asp.Net Validation kontrolleri yardımı ile gerçekleştireyim şeklinde aklınıza çözüm gelebilir. Evet yapabiliriz. Fakat bizim ana amacımız hazırlanan internet sayfalarınız daha performanslı bir şekilde açılabilmesi olduğu için Validation kontrolleri yerine başka bir kontrol kullanalım. Fakat unutmayalım ki MVC Framework ile hazırlamış olduğumuz uygulamalarda Asp.Net kontrolleri kullanılması mümkündür. Ama biz controller tarafında hazırlayacak olduğumuz işlemler yardımı ile Validation kontrollerini kullanmak istiyoruz. Çünkü bizler web sayfasının markup kodunda asp kontrolleri yerine Html.* şeklinde HTML içeriklerini kullanmak istemekteyiz. Bu yazımız boyunca bu işlemleri nasıl yapabileceğimize detaylı bir şekilde incelemeye çalışıyoruz olacağız.

Validation işlemlerimizi yapabilmemiz için Model kavramını incelerken kullanmış olduğumuz proje üzerinde değişiklikler yaparak başlıyoruz. İlk olarak veri tabanımıza Dukkan isimli bir tablo daha ekliyoruz ve alanları olarak;
• Id
• Name
• Description
• UnitPrice
• Stock
belirledikten sonra Entity modele ekleme işlemini gerçekleştirebilmek için *.edmx ara yüzünün üzerinde sağ tıklama yaptıktan sonra Update Model from Database seçeneğine tıklayarak yeni bir tablo ekleyebileceğimiz ekrana geliyoruz.



Karşımıza gelen ekranda Tables seçeneğinden yeni eklemek istediğimiz tabloyu seçtikten sonra tamam seçeneğine basarak Entity modelinin içeriğindeki tablo sayısını arttırıyoruz. Ayrıca daha önceki yazılarımızda değinmiş olmamıza karşın tekrardan hatırlamak gerekirse, Entity Model 'in içerisine tablo,view ve store prodecure (sp) ekleyebilmemiz mümkündür.



Eklemiş olduğumuz tablo entity modelde gözükmüştür. Bu tabloya ilişkin işlemleri yapabilmemiz için projeye bir tane Controller sınıfı ekliyoruz. İçeriğinde ilk olarak tablo içerisinde yer alan verilerin gözükmesi için index() metodunu dolduruyoruz. Sonrasında da herhangi bir veri yoksa yeni bir kayıt ekleme işlemini yapacağız. Bu noktada dikkat edeceğimiz yer başlamaktadır. Yazımızın başlarında Validation işlemlerini açıklarken en sık kullanım yerinin başında son kullanıcıya veri ekleme izni verilen yerlerde olduğundan bahsetmiştik. İşte bizde bu controller içerisinde yeni bir kayıt eklemek istediğimiz durumda Validation işlemlerini nasıl uygulayabileceğimize göz atacağız. Bunun için Create metodunda aşağıdaki eklemeleri ve düzenlemeleri yapıyoruz.

Controller\ProductController.cs
public ActionResult Create()
{
    return View();
}

//
// POST: /Product/Create

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude="Id")] Dukkans dukkansToCreate)
{

    //Kontrollerin yapıldığı kısımdır.
    if (dukkansToCreate.Name.Trim().Length == 0)
        ModelState.AddModelError("Name", "İsim degeri bos gecilemez...");
    if (dukkansToCreate.Description.Trim().Length == 0)
        ModelState.AddModelError("Description", "Aciklama degerleri bos gecilemez");
    if(dukkansToCreate.UnitStock<0)
        ModelState.AddModelError("UnitPrice","UnitPrice degeri 0 dan az olamaz...");
    if (ModelState.IsValid)
    return Create();
    try
    {
        // TODO: Add insert logic here
        _db.AddToDukkansSet(dukkansToCreate);
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

Entity Model 'de yer alan veri tabanı tablosuna ilişkin elemanları tek tek değer kontrolü ettikten sonra bizim belirtmiş olduğumuz özellikler kriterleri kullanıcının girmiş olduğu veriler geçemezse ModelState.AddModelError() ile işlem yapılacak alan için istenilen mesaj verilebilir duruma gelinmiştir. Peki, "bizler hiç kontrol eklemezse varsayılan olarak yaptığı kontroller var mıdır?" şeklinde aklınıza bir soru takılabilir. Cevabı ise, evet vardır. Veri tabanı üzerindeyken tablonuzu oluşturma esnasında alanlardan boş geçilemez olarak tanımlamış olduğunuz alanlarda varsayılan olarak kontrol yapılmaktadır ve yapılan kontrol verilerin girilip girilmediği kontrolüdür.

MVC uygulamalarında kullanıcıların göreceği katmana View denilmekteydi ve bu sayfaları controller da oluşturulmuş olan metotlar yardımı ile basitçe oluşturabiliyorduk. Şimdi tekrardan kısaca bu işleme göz atmak gerekirse,

İlk olarak oluşturmuş olduğumuz metodun üzerine geliyoruz ve sağ tıklama sonrası addView seçeneğine tıklıyoruz.



Bir sonraki adımda karşımıza gelen ekranda Oluşturmak istediğimiz View 'ın adını (eğer vermezsek varsayılan olarak metodun adını alacaktır) ne tür işlem yapacağımızı ve veri sınıfının ne olacağını sormaktadır. Veri sınıfı bölümünde model isim alanı içerisinde yer alan nesnelerden tablomuzun isminin olduğu seçeneği seçmemiz durumunda yapmak istediğimiz işlemler sorunsuzca çalışacaktır. Aksi durumda çalışma anında hata ile karşılacaksınız.



Yaptığımız işlemler sonrasında view sayfasını oluşturmuş bulunuyoruz. Artık bu sayfanın içeriğini inceleyebiliriz.

View\Product\Create.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<FilmUygulama.Models.Dukkans>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Create</h2>

<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Id">Id:</label>
            <%= Html.TextBox("Id") %>
            <%= Html.ValidationMessage("Id", "*") %>
        </p>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name") %>
            <%= Html.ValidationMessage("Name", "*") %>
        </p>
        <p>
            <label for="Description">Description:</label>
            <%= Html.TextBox("Description") %>
            <%= Html.ValidationMessage("Description", "*") %>
        </p>
        <p>
            <label for="Price">Price:</label>
            <%= Html.TextBox("Price") %>
            <%= Html.ValidationMessage("Price", "*") %>
        </p>
        <p>
            <label for="UnitStock">UnitStock:</label>
            <%= Html.TextBox("UnitStock") %>
            <%= Html.ValidationMessage("UnitStock", "*") %>
        </p>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>dasda

HTML elementinin özelliklerinden ValidationMessage() ile kullanıcıların veri girişinde yapmış oldukları hataları gösterebilmemize olanak tanımaktadır. Gerekli kontrolleri hatırlayacağınız üzere ProductController sınıfının içerisinde yer alan Create metodunun içerisinde yapılmıştı. Sizler index() metodunun dışında yer alan sayfaları da oluşturarak uygulamanızı daha da kullanışlı bir biçime getirebilmeniz mümkündür. Eğer bu işlemler esnasında herhangi bir zorluk yaşıyorsanız Asp.Net MVC Framework ile ilgili geçmiş yazıları okuyarak eksiklerinizi tamamlayabilirsiniz. Gerekli sayfaları oluşturduk ve web sayfasını çalıştırıyoruz.



Adres çubuğuna dikkat edersek, oluşturulan controller in adına göre view katmanına alt klasörler oluşturuldu ve o klasörün içerisinde oluşturulmuş olan index sayfası çağırıldı. Fakat tablomuzda hiç bir kayıt olmadığı için karşımıza sadece tablo alanlarının isimleri gelmektedir.



Gördüğünüz üzere ProductController sınıfında Create() metodunda kullanılacak değerler için eklemiş olduğumuz bütün Validation kontrolleri gerçekleşmiştir. Çok ufak bir hatırlatma yapmak gerekirse, Create() metodunda [Bind(Exclude="")] kullanım şekli veri tabanından ya da başka bir yerden otomatik olarak eklenecek olan verileri belirtmektedir. Bu bize belirtilen alan için değer bekleme eğer ki alan view sayfa üzerinde kaldırılmadıysa dahi girilen değeri görmeden işlemleri yapmaya devam et anlamına gelmektedir.

Yazımızda değinmiş olduğumuz konulara kısaca bir göz atmak gerekirse; İlk olarak Validation işlemlerinin hangi durumlarda, nasıl ve hangi amaçlarla kullanıldığını açıklamaya çalıştık. Bir sonraki adımımızda bir proje oluşturarak tablomuzu Entity Data model 'e ekleyerek proje içerisinde kullanılabilir bir duruma getirdikten sonra tablo için gerekli olan controller sınıf oluşturuldu. MVC Framework ile hazırlanmış olan web uygulamalarında Validation işlemlerini kullanmak istediğimizde Controller sınıflarının içerisinde yapmamız gerektiğini ve ModelState.AddModelError() özelliğini kullanmamız gerektiğine göz attık. Daha sonra oluşturmuş olduğumuz metodun view sayfasını nasıl oluşturabileceğimizi tekrardan hatırlayarak Create sayfasını oluşturduk. Markup kod tarafına otomatik olarak eklenen kodları incelediğimiz de gözümüze HTML elementinin bir başka özelliği çarpmaktadır ki bu özellik bizim uygulamak istediğimiz Validation işlemlerinde en çok yarayan '*' 'ı koymaktadır. HTML.ValidationMessage() özelliği ile de hatalı girilen bileşenlerin yanına kırmızı bir * koyarak daha da belirgin olabilmesine olanak tanımaktadır. En son olarak da yaptığımız işlemleri internet tarayıcında kontrol ederek işlemlerimizi tamamladık.

Umarım yararlı olabilmiştir.

Turhal Temizer
info@turhaltemizer.com

Pazar, Temmuz 12, 2009

Asp.Net MVC Framework - Master Pages Kullanımı - II

Asp.Net MVC Framework ile bugüne kadar bir çok konuya değinme şansı bulduk ve temel kavramlarını rahatlıkla yapabilir duruma geldik. Görsel olarak uygulamalarımızı daha da kuvvetli duruma getirebilmek için bir önceki MVC Framework yazımızda Master Page 'i nasıl kullanabileceğimize değinmiştik. Peki bu noktada aklımıza bir kaç soru takılıyor. Eğer tasarımsal öğelerini rahatlıkla düzenleyebiliyorsak hazır şablonlar da olmalı ve onlar yardımı ile de düzenleyebiliriz şeklinde sorular gelmektedir. Bunun cevabı ise oldukça basittir. MVC ile geliştirilen uygulamalarda kullanılmak üzere oluşturulan tasarım galerisi sayfası mevcuttur. Buradan erişebilmemiz mümkün olacaktır.

Yazımızın girişinde de anlayacağınız gibi farklı tasarım şablonlarını uygulamalarımızda nasıl kullanabileceğimizi inceleye çalışacağız. Ama ilk olarak bu değişiklikleri uygulayabilmemiz için bir projeye ihtiyacımız vardır. Daha önceki yazılarımızdan yararlanarak hızlıca bir tane oluşturuyoruz.



İlk olarak yapmamız gereken yukarıda görmüş olduğumuz standart MVC Framework tasarımını düzenleyecek görsel şablonu seçmemiz gerekiyor. Bu işlemi gerçekleştirmek için MVC Framework galeri sitesine girmemiz gerekecektir. Sitemize http://www.asp.net/mvc/gallery/ adresinden ulaşabilmemiz mümkündür.



Yukarıda görmüş olduğunuz tasarımların dışında daha onlarca tasarım yer almaktadır. Bu tasarımlardan herhangi birini seçerek web sitemize uygulamayabilmemiz mümkündür. Beğendiğimiz herhangi bir tasarımı beğeniyoruz ve aşağıdaki işlemleri uygulamaya başlıyoruz.

1. Beğenmiş olduğumuz tasarımı bilgisayara indirebilmek için tasarımın hemen altında yer alan Download seçeneğine tıklıyoruz.
2. İndirmiş olduğunuz sıkıştırılmış dosyanın üzerinde sağ tıklama sonrası özelliklerine giriyoruz ve Unblock seçeneğine tıklıyoruz.



3. Tasarımı sıkıştırılmış dosyanın içerisinden çıkartıyoruz.
4. Çıkartmış olduğunuz dosyalar CS ve VB için oluşturulmuştur. Hangi programlama dili ile projenizi geliştiriyorsanız onun içeriğini kopyalıyorsunuz.
5.
Geliştirmekte olduğunuz MVC Framework web projesinin bilgisayarınızda olduğu klasöre gidiyorsunuz ve kopyalamış olduğunuz dosyaları yapıştırıyorsunuz ve benzer dosyaları değiştireyim mi diye soran ekranda evet seçeneğini seçiyoruz.



6. Artık projenizin tasarımı indirmiş olduğunuz tasarıma göre güncellenmiştir. Yapmanız gereken son işlem [YourProjectName] yazan yerleri kendi projenizin ismi ile değiştirmek olacaktır.



Yapılan işlemler sonucunda projenin almış olduğu görünüme bir göz atalım. Bakalım seçmiş olduğumuz tasarım hazırlanmış olan projenin üzerinde nasıl gözüktü.



Artık oldukça şık tasarıma sahip bir web sitesine sahibiz.

Şimdi eklemiş olduğumuz tasarımı bizlerde biraz daha düzenleyerek çok daha görsel bir görünüme getirelim. Örneğin düzenle, detaylar ve yeni oluştur yazılarını ikon olarak değiştirip çok daha anlaşılır bir görünüme kavuşturalım. bu işlemi gerçekleştirmek için yapmamız gereken ister bir tasarımcı tarafında oluşturulmuş olan ister internet üzerinden bulunmuş resimleri yazıların yerine kullanmak olacaktır.

Ekran üzerinde controller üzerinden gelen bilgilere göre işlemlere yönlendirirken Html.ActionLink() 'i kullanıyorduk. Fakat bu yöntem içerisine resim ekleyebilmemiz mümkün değildir. Aldığı parametreler Html.ActionLink("string","ActionStrign",RouteValue") şeklindedir. Projelerde kullanım şeklide aşağıdaki gibi olmaktadır.

<%= Html.ActionLink("Düzenle", "Edit", new { id=item.Id }) %>
|
<%= Html.ActionLink("Detaylar", "Details", new { id=item.Id })%>

Fakat bizim bu noktada yapmak istediğimiz proje eklenmiş ikonları detaylar ve düzenle bölümünde gösterirken linkleri de bu resimler üzerinde aktif olarak kullanılmasını isteyeceğiz. Tabii tekrar hatırlamak gerekirse bu işlemi Html.ActionLink() yardımı ile yapamıyoruz. Bunun için Url.Action() 'ı kullanırsak yapmak istediğimizi gerçekleştirebilir duruma geleceğiz. Çünkü bu parametre olarak Url.Action("ActionName","RouteValue") almaktadır. Bu durumda bizde <a href=""></a> taglarının arasında Url.Action() 'ı kullanırsak istemiş olduğumuz yönteme gelmiş olacağız. Ne gibi derseniz, web sayfalarında link vermek istediğimizde bizden linkin görünebilmesi için bir metin istemektedir. Bizler metin yerine resmi gösterirsek istediğimiz sonuca ulaşmış olacağız. Bu durumda yapmak istediklerimiz kod olarak görmek istersek aşağıdaki gibi bir görünüme sahip olacağız.

<td class="actions edit">
   <a href='<%= Url.Action("Edit", new {id=item.Id}) %>'>
      <
img src="../../Pictures/component_edit.gif" alt="Edit" width="20" height="20"/></a>
</td>
<td class="actions details">
   <a href='<%= Url.Action("Details", new {id=item.Id}) %>'>
      <
img src="../../Pictures/components.gif" alt="Detaylar" width="20" height="20"/></a>
</td>

Düşündüğümüz gibi controller dan gelen action ları link içerisinde tanımladık ve metin gireceğimiz bölümlere projenin içerisinde yer alan resim değerlerini vererek üzerine tıklandığında istenilen değerin detaylarına gitmesine olanak tanıdık. Peki yeni bir kayıt oluşturmak istediğimiz durumda ne gibi bir işlem yapmamız gerekmektedir. Ne gibi bir fark var diyebilirsiniz. Çok ufak bir fark bulunmaktadır. Bu da RouteValue parametresinin bulunmamasıdır. Fakat bizlere biliyoruz ki hem Html.ActionLink() 'te hem de Url.Action() RouteValue parametresi boş bırakılabilmektedir. Bu sebepten ötürüdür ki yeni bir kayıt oluşturma esnasında yukarıda vermiş olduğumuz kod parçasını olduğu gibi kullanmakla beraber yalnızca new{id=item.Id} parametresinin olduğu değeri silmemiz yeterli olacaktır. Yapmış olduğumuz işlemler sonrasında projemizin nasıl bir görünüme sahip olduğuna göz atmak gerekirse,



Oldukça hoş bir uygulamaya sahip olduk. Hem görsel açıdan hem de performans açısından başarılı bir uygulamamız oldu. Fakat değinmek istediğim bir nokta var. Eklemiş olduğumuz resimlerin boyutları oranında sayfanın açılmasında çok ufakta olsa bir yavaşlama gözlemlenmektedir. Bu açıdan resim eklerken boyutlarına mümkün oldukça dikkat ediniz.

Geldik bir MVC Framework yazımızın daha sonuna. Nelere değindiğimize kısaca göz atmak gerekirse, MVC Framework ile hazırlanan uygulamaların varsayılan tasarımının dışına çıkmak için Master Pages üzerinde yapabileceğimiz değişiklikleri bir önceki yazımızda inceledikten sonra bu yazımızda da MVC uygulamaları kullanılabilecek tasarımların yer aldığı galeriden yararlanarak seçmiş olduğumuz tasarımı kendi uygulamamız üzerinde nasıl kullanabileceğimize ve üzerinde düzenleme yapmak istediğimiz hangi adımları ve değişiklikleri yapmamız gerektiğini incelemeye çalıştık. Bir sonraki yazımızda görüşünceye dek, esenlikle kalın...

Umarım yararlı olabilmiştir.

Turhal Temizer
info@turhaltemizer.com

Çarşamba, Temmuz 08, 2009

Asp.Net MVC Framework - Master Pages Kavramı - I

Microsoft 'un web projelerini hazırlarken bizlere mimari tasarıları daha basit ve kullanışlı bir biçimde kullanmamızı sağlayan Asp.Net MVC Framework 'ü daha önceki yazılarımızda detaylı bir biçimde tanımaya çalıştık. Peki neler yapabiliyorduk. Son kullanıcıdan gelen istekler doğrultusunda başka bir sayfaya nasıl yönlendirebileceğimizi, Controller katmanı ile veri tabanı işlemlerini nasıl işleyip görsel sayfaya ileteceğimizi, model katmanı yardımı ile veri tabanı ile haberleşmelerin çok daha basit bir şekilde yapılabileceğini, veri tabanını aktif olarak kullandığımızda nasıl bir uygulama geliştirdiğimizi ve view sayfaları nasıl kolayca oluşturabileceğimizi detaylı olarak daha önceki yazılarımızda inceledik ve neler yapabileceğimizi gördük. Ayrıca uygulamalarımızda MVC tasarımını kullandığımızda daha önceden oldukça fazla uğraştığımız işlemleri ne kadar kolaylıkla yapabildiğimizi defalarca yapmış olduğumuz pratiklerde doğrulamış olduk. Bu yazımızda ise Asp.Net sayfalarında tasarım standardı açısından sıkça kullandığımız Master Pages kavramını MVC Framework 'te kullanım yapısını detaylı olarak inceliyor olacağız.

Asp.Net uygulamaların Master Page kullanmamızın sebebini kısaca hatırlayacak olursak. Benzer tarzda tasarım şablonu kullanacak olduğumuz sayfalarda tekrardan o tasarımsal öğeleri serverdan çağırıp sayfa üzerinde yüklenmemesini beklememek için oluşturulmuş başarılı bir yapıdır. Özellikle tasarım yapısı üzerinde herhangi bir değişiklik yok ise ve sadece içerikler değişecekse çok önemli bir tercih durumundadır. Aynı Asp.Net uygulamalarında olduğu gibi MVC uygulamalarında da Master Page kavramı önemli bir yer tutmaktadır. Varsayılan olan mavi bir tasarımı olan Master Page kullanılmaktadır. Peki biz bu tasarımı değil de kendi tasarımımızı Master Page 'e taşımak istersek neler yapmamız gerekir. Gelin hep birlikte bunu incelemeye çalışalım.

Her zaman olduğu gibi ilk olarak yapmamız gereken Visual Studio 2008 SP1 geliştirme ortamında bir Asp.Net MVC Framework Web uygulaması oluşturuyoruz. Proje dosyasının içerisinden ilk olarak varsayılan olarak oluşturulan Master Page 'in yerini bulalım.



MVC tasarımını dikkate alarak araştırmalarımızı yaptığımızda görsel öğelerin view katmanında olduğunu görürüz. Master Page her yerde kullanılacak bir içerik olduğu içinde view içerisinde Shared klasörünün içerisinde yer alır.

Biz uygulamamızda bu otomatik olarak oluşturulan Master Page 'i kullanmak yerine kendimize bir tane oluşturalım. Ama ilk olarak oluşturulmuş olan Site.Master 'ı siliyoruz. Sonrasında da Add- NewItem yolunu izleyerek web sitesine yeni bir Master Page ekliyoruz.



Master Page 'i sorunsuzca projeye ekledikten sonra nasıl bir içerik oluşturulacağının düşünülmesinin zamanı gelmiştir. Basit olması açısında içeriğe göre değiştirilebilir iki sütun ekleyelim. Bu değişen içerik eklemeyi Asp.Net 'ten de alışık olduğu gibi <asp:ContentPlaceHolder> yardımı ile yapacağız. İçeriği arttırdıktan sonra temel CSS ile Master Page 'in içerisine stil özellikleri de ekliyoruz ve bu yaptığımız işlemler sonrasında elimizdeki değişikler aşağıdaki gibi olacaktır.

View\Shared\Site.Master
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
   <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>

   <style type="text/css">
      html
      {
         background-color:Gray;
      }

      .column
      {
         float:left;
         width:300px;
         border:solid 1px black;
         margin-right:10px;
         padding:5px;
         background-color:white;
         min-height:500px;
      }

   </style>
   <asp:ContentPlaceHolder ID="head" runat="server">
   </asp:ContentPlaceHolder>
</head>
<body>
   <h1>Sitem</h1>

   <div class="column">
      <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
      </asp:ContentPlaceHolder>
   </div>
   <div class="column">
      <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
      </asp:ContentPlaceHolder>
   </div>
</body>
</html>

Eklemiş olduğumuz içerik kontrollerini body 'nin içerisine <div> taglarının arasına yerleştiriyoruz. Ayrıca div taglarının sütün gibi hareket etmesi için stil özelliğine daha önceden hazırlamış olduğumuz column 'u tanımlıyoruz. Yaptığımız bu işlemler sonucunda Master Page 'in görünümü aşağıdaki gibi olacaktır.



Basit fakat bizlerin hazırlamış olduğu bir Master Page 'e sahip olduk.

Master Page 'i Kullanan View Sayfa Oluşturmak

Asp.Net uygulamalarında Master Page 'ten yararlanarak web sayfaları oluşturabilmemiz mümkündü. Bunun bize en büyük yararı oluşturmuş olduğumuz sayfalarda Master Pages üzerinde belirtmiş olduğumuz içerik kontrol alanlarının düzenlenebilmesi ve diğer taraflar üzerinde herhangi bir değişiklik yapmadan hazırlıyor olmamızdır. MVC Framework 'ten yararlanarak hazırlamış olduğumuz web sayfalarında da Master Page Asp.Net uygulamalarında olduğu gibi kullanılmaktadır.

View klasörünün içerisinde yer alan Home klasörünün üzerinde sağ tıklama sonrasında karşımıza gelen menüden Add - NewItem seçeneğine tıklayarak ekrandan MVC View Content Page i seçerek Master Page 'i kullanabileceği bir web sayfa oluşturmaya başlıyoruz.


Sayfa tipimizi seçip ekle dediğimizde hazırlamış olduğumuz Master Page 'ler den istediğimizi seçmek için bir ekran çıkacaktır.


Tamam dedikten sonra artık Master Page 'i kullanan bir web sayfası uygulamamızda oluşturulmuş olacaktır. Oluşturulan sayfanın arka plan kodları aşağıdaki gibi oluşturulmuştur.

View\Home\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
</asp:Content>

Standart olarak projelere eklenmiş olan *.aspx sayfalardan farklı olarak HTML ve Body tagları yer almaktadır. Bu taglar Master Page de oluşturulduğu için yalnızca belirttiğimiz içerik kontrol alanları sayfada gözükmüştür ve sayfa içerisinde kullanıcılara göstermek istediğimiz içerikleri buralardan yayınlarız. Örnek olması açısında body taglarının içerisine eklemiş olduğumuz <asp:content> 'lerin içerisinde biraz değişiklik yaparak aldığımız sonuca hep birlikte çok atalım.

View\Home\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
   İlk içerik kontrol alanı
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
   İkinci içerik kontrol alanı
</asp:Content>

Yaptığımız düzenleme sonrasında ekran değişikliğimiz aşağıdaki gibi olacaktır.



Yapılmış olan değişikler sonrasında web sayfamızın içeriği istediğimiz gibi olmuştur.

Master Page yardımı ile oluşturulan view sayfanın içeriğini düzenlemek

İlk olarak düzenleme yapağımız yer sayfamızın başlığı olacaktır. Oluşturmuş olduğumuz web sayfası internet tarayıcısında açıldığında pencerenin en üst kısmında yer alan bölümü düzenleyelim. Asp.Net ten ve diğer bütün web sayfası kodlama yapılarından alışık olduğumuz üzere title bölümünde belirtmemiz yeterli olacaktır.

Sayfamızın markup kod tarafında en üstte yer alan <Page> </Page> bölümün aralığının içerisinde yer alan title özelliğini değiştirerek sayfa başlığını sorunsuzca oluşturmuş oluruz.


Yapmış olduğumuz işlemi hazırlanmış olan Master Pages ile ilişkilendirerek tekrardan yapalım. Bu durumda ilk olarak oluşturulan Master Pages içerisine koyduğumuz içerik kontrol alanlarını hatırlamamız gerekir ve bir tane head bölümünün içerisine <asp:contentplaceholder> ekledik. Alana başlık, meta ve diğer birçok kriteri ekleyebilmemiz mümkündür. Bu özellikten yararlanarak aspx sayfasının içerisinde aşağıdaki değişiklikleri uyguluyoruz.

View\Home\Index.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
   <title>Başlık buraya yazılacak</title>
   <meta name="description" content="İçindekiler buraya" />
   <meta name="keywords" content="ana arama kriterleri buraya" />

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
   İlk içerik kontrol alanı
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
   İkinci içerik kontrol alanı
</asp:Content>

Asp.Net uygulamaları ile uygulamadığımız tekniklerin birebir aynısıdır. Bu örneklerin bu kadar detaylı olarak gösterilmesinin sebebi Master Pages kavramının temel yapısının alışık olduğumuz Asp.Net Master Pages kavramından bir farkının olmadığını da göstermek amacıyladır. Yapmış olduğumuz işlemler sonrasında karşımıza gelen ekran görüntüsü aşağıdaki gibi olacaktır.



Yaptığımız işlemler sonucunda gayet başarılıyız. :)

Bu yazımızda Asp.Net MVC Framework ile hazırlanmış olan uygulamalarda Master Pages kavramını nasıl kullanabileceğimizi ve içerik düzenlemelerini nasıl kullanabileceğimizi detaylı bir biçimde incelemeye çalıştık. Bir sonraki MVC Framework yazımızda Master Pages kavramını incelemeye devam ederken veri tabanı işlemleri ile ilişkilerine de detaylı bir biçimde değineceğiz.

Umarım yararlı olabilmiştir.
info@turhaltemizer.com