Delegeler ve Olaylar (Delegates and Events) – II

Olaylar(Events)
Olaylar, mouse ile tıklama, klavyeden tuşa basma gibi kullanıcının işletim sistemi üzerinden gerçekleştirdiği faaliyetlerdir. Bu şekilde, uygulamamız içerisinde meydana gelen durum değişikliklerine karşı hassas olan ve bu değişiklikler doğrultusunda yönlendirilebilen programlama modeline olay güdümlü programlama (event driven programming) denir. Bu modeldeki programlar, bir şeyler yapmak için bazı şeylerin gerçekleşmesini beklerler. Bir bileşen üzerinde meydana gelen olayların takipçisi olup onları yakalayan mekanizmaya olay yöneticisi (event handler) denir. Olay tutucusu veya işleyicisi olarak ta tanımlanan event handler, ilgili olay gerçekleştiği zaman tetiklenir. Olay yöneticilerinin yönlendirilmesi bizim tarafımızda kodlanır, olay yöneticisinin olay gerçekleştikten sonra hangi işlemleri yapacağını delegatelerle tanımlarız. Yani olay yöneticileri, delegatelerle temsil edilir.
Eventleri aktif olarak Windows programlamada control’ler için kullanırız. Örneğin kullanıcının mouse ile tıklaması Click event’inin, klavyede tuşa basması KeyPress event’inin oluşmasına neden olur. Bize düşen, Click, KeyPress gibi event’lerin altını doldurmaktır yani bu eventleri delegate aracılığıyla metodlarla ilişkilendirmektir.
Bu bölümde derleme zamanında olay yönetimini ve çalışma zamanında olay yönetimini(dinamik olay yönetimi) işleyeceğiz.
VB.NET Eventleri iki farklı yöntemle tanımlayabiliriz. İlk yöntem, bir delegate oluşturmak ve event’i bu delegate türünden tanımlamaktır. İkinci yöntem ise delegate tanımlamadan doğrudan event’i, formatıyla birlikte tanımlamaktır. Bu yöntem delegate kullanılmadığı anlamına gelez çünkü derleyici bu durumda da event için bir delegate yaratır.
C# Bir eventi tanımlamadan önce o event’i temsil edecek delegate’in tanımlanması gerekir.
Yeni bir event oluşturmak için “event” sözcüğü kullanılır. Oluşturulan eventleri tetiklemek için VB.NET’te RaiseEvent sözcüğü kullanılırken C# tarafında event’in ismi kullanılır.

'Eventin türünü belirleyen delegate
Public Delegate Sub ClickEventHandler(ByVal Mesaj As String)

Public Class CustomControl
    'Bu Class için bir event tanımlayalım.
    Public Event Click As ClickEventHandler
    'Public Event Click(ByVal Mesaj As String)

    'Click eventini tetikleyecek metod (Event raising method)
    Sub OnClick(ByVal Mesaj As String)
        RaiseEvent Click(Mesaj)
    End Sub
End Class
//Eventin türünü belirleyen delegate
public delegate void ClickEventHandler(string Mesaj);

class CustomControl
{
    //Bu Class için bir event tanımlayalım.
    public event ClickEventHandler Click;

    //Click eventini tetikleyecek metod (Event raising method)
    public void OnClick(string Mesaj)
    {
        Click(Mesaj);
    }//OnClick

}//CustomControl

Doğru şartlar gerçekleştikten sonra event tetiklenir ve bağlı olduğu metodları çalıştırır. Bu metodlara Event Handler denilir. Event handling işlemini dinamik olarak çalışma zamanında yeniden implemente edebiliriz. Çalışma zamanında bir eventi bir metoda bağlamak için (hooking) VB.Net’te AddHandler sözcüğü, C#’ta ise += operatörü kullanılır. Evente eklenmiş metodu kaldırmak için de (unhooking) VB.Net’te RemoveHandler sözcüğü, C#’ta da -= operatörü kullanılır. Burada dikkat edilmesi gereken konu, eventin bağlanacağı metodların signature’leri event’in türü olan delegate ile aynı olmalıdır.

Module EventOrnek
    Sub Main()
        Dim o1 As New CustomControl
        AddHandler o1.Click, AddressOf MesajYaz
        AddHandler o1.Click, AddressOf MesajBuyukYaz

        'eventin çalışmasına sebep olan işlem
        o1.OnClick("Tatlı dil, her kapıyı açan sihirli bir anahtardır.")
        Console.WriteLine()

        'MesajYaz metodunu listeden çıkarıyoruz.
        RemoveHandler o1.Click, AddressOf MesajYaz
        o1.OnClick("Erdem , iyiyi elde etme gücüdür.")

        Console.ReadLine()
    End Sub

    Sub MesajYaz(ByVal Mesaj As String)
        Console.WriteLine(Mesaj)
    End Sub

    Sub MesajBuyukYaz(ByVal Mesaj As String)
        Console.WriteLine(Mesaj.ToUpper)
    End Sub

End Module
class Class1
{
    static void Main()
    {
        CustomControl o1 = new CustomControl();
        o1.Click += new ClickEventHandler(MesajYaz);
        o1.Click += new ClickEventHandler(MesajBuyukYaz);

        //eventin çalışmasına sebep olan işlem
        o1.OnClick("Tatlı dil, her kapıyı açan sihirli bir anahtardır.");
        Console.WriteLine();

        //MesajYaz metodunu listeden çıkarıyoruz.
        o1.Click -= new ClickEventHandler(MesajYaz);
        o1.OnClick("Erdem , iyiyi elde etme gücüdür.");

        Console.ReadLine();
    }

    static void MesajYaz(string Mesaj)
    {
        Console.WriteLine(Mesaj);
    }

    static void MesajBuyukYaz(string Mesaj)
    {
        Console.WriteLine(Mesaj.ToUpper());
    }

}//Class1

Tatlı dil, her kapıyı açan sihirli bir anahtardır.
TATLI DİL, HER KAPIYI AÇAN SİHİRLİ BİR ANAHTARDIR.
ERDEM , İYİYİ ELDE ETME GÜCÜDÜR.

Örnekte gerçek bir kontrol olmadığı için event’i OnClick ile tetikliyoruz. Görüldüğü gibi birbirleriyle konuşacak yapıların signatureleri aynı biçime sahip. Örneğin bir metodu windows uygulamasında bir butonun click eventine bağlamak için metodun signature’i butonun click eventi ile aynı olmalıdır. Butonların click eventinin formatı şu şekildedir;

Public Event Click As EventHandler

Public Delegate Sub EventHandler(ByVal sender As Object, ByVal e As EventArgs)
public event EventHandler Click;

public delegate void EventHandler(object sender, EventArgs e);

Metadata kodlarından görüldüğü gibi kontrollerin click event’i System.EventHandler isimli delegate türüne sahiptir. Dolayısıyla çalışacak metod da şu şekilde tanımlanmalıdır.

AddHandler Button1.Click, AddressOf Metod

Sub Metod(ByVal sender As System.Object, ByVal e As System.EventArgs)
    'İşlemler
End Sub
button1.Click += new EventHandler(Metod);

void Metod(object sender, System.EventArgs e){
	//İşlemler
}

Bunlara ek olarak VB.Net’te eventleri yakalamanın kolay bir yolu da WithEvents ve Handles ikilisini kullanmaktır. Bu sözcükler daha çok Windows GUI (Graphical User Interface-Grafik Ara Birimi) uygulamalarında programlama, derleme zamanında metodları ilişkilendirmek için kullanılır. WithEvents ifadesi, derleyiciye yaratılan nesnenin eventleriyle birlikte kullanılacağını ifade eder. Handles ifadesini kullanmak için nesneleri WithEvents ile tanımlamalıyız. Aşağıdaki örnekte bu ifadelerin kullanımı gösterilmiştir.

Friend WithEvents o1 As New CustomControl

Sub Main()
    o1.OnClick("Erdem , iyiyi elde etme gücüdür.")
    Console.ReadLine()
End Sub

'Handles sözcüğü ile MesajYaz metodu, o1 nesnesinin Click eventine bağlanmıştır.
Sub MesajYaz(ByVal Mesaj As String) Handles o1.Click
    Console.WriteLine(Mesaj)
End Sub

Handles ifadesiyle birden fazla event’i aynı metoda bağlayabiliriz. Bunun için event’leri virgül ile ayırmamız yeterli olacaktır.

Friend WithEvents o1 As New CustomControl
Friend WithEvents o2 As New CustomControl

Sub Main()
    o1.OnClick("Erdem , iyiyi elde etme gücüdür.")
    o2.OnClick("Erdem , iyiyi elde etme gücüdür.")
End Sub

Sub MesajYaz(ByVal Mesaj As String) Handles o1.Click, o2.Click
    Console.WriteLine(Mesaj)
End Sub

Delegeler ve Olaylar (Delegates and Events) – II” üzerine 14 düşünce

  1. sinan

    erdem,Su imkan varmi main de dugmeye bastinizda customcontrolda olan bir event calistira bilirmisiniz ?
    yardimci olursaniz sevinirim
    sagilarla

    Cevapla
  2. Ahmet Kaymaz Yazar

    Çalıştırmamak için bir neden görmüyorum. O event’in raise ettiği yordamı kullanmanız yeterli olacaktır.

    Cevapla
  3. sinan

    namespace test.CustomControls
    {
    public class MbTextBox : TextBox
    { protected override void OnLostFocus(RoutedEventArgs e)
    {
    ValidateControl();
    base.OnLostFocus(e); }
    ValidateControl(){}; }
    }namespace TestApp
    {
    ///
    /// Interaction logic for Window1.xaml
    ///
    public partial class Window1 : Window
    {
    public Window1()
    {
    InitializeComponent(); button1.Click += new ????? } private void button1_Click(object sender, RoutedEventArgs e)
    { }
    }
    }yapamak istedigim kendim Bir TextBox. ve bu TextBox TestApp da kulanacam
    birden fazla TextBox kulanacam forum icin.TextApp Okey Button var.
    Button na basinca tum TextBoxlarin actievlesitrecek yani OnLostFocus ve ya ValidateControl cagiracak.
    button1.Click += new ?????Bu konuda kucuk bir orenek code varmi.
    Yardiminiz icin tesekurler
    Umarim yazdiklarim acikliycidir anlasilmayan yer varsa sorularinizi bekliyorum.
    sagilar

    Cevapla
  4. Ahmet Kaymaz Yazar

    Şu anda bulunduğum yerde WPF ortamı olmadığı için denemedim ancak sorununu anladığım kadarıyla şu şekilde rahatlıkla çözebilirsin.namespace test.CustomControls
    {
    public class MbTextBox : TextBox
    {
    protected override void OnLostFocus(RoutedEventArgs e)
    {
    ValidateControl();
    base.OnLostFocus(e);
    }
    public void ValidateControl(){
    MessageBox.Show("ValidateControl cagrildi.");
    }
    }
    }
    protected override void OnLostFocus(RoutedEventArgs e)
    {
    ValidateControl();
    base.OnLostFocus(e);
    }Ardından tıklanmış olan Button kontrolünün eventine ait yordam içerisinde şu şekilde bir çağrım yapmak yeterli olacaktır.private void button1_Click(object sender, RoutedEventArgs e)
    {
    this.Title = "Merhaba";
    MbTextBox oTxt = new MbTextBox();
    oTxt.ValidateControl();
    }

    Cevapla
  5. sinan

    Evet bu bir yontem ama ben Test app da
    birden cok TextBox kulaniyorum textbox1
    textbox2
    textbox3
    textbox4 private void button1_Click(object sender, RoutedEventArgs e)
    {
    this.Title = “Merhaba”;
    MbTextBox oTxt = new MbTextBox();
    oTxt.ValidateControl();
    }Bu sekil yanliz oTxt validere yapiyor
    benim aradigim dugmeye basinca tum TextBoxlar hemen validere yapacak
    boyle bir cozum nasil uygulaya bilirim ?

    Cevapla
  6. Ahmet Kaymaz Yazar

    WPF’te dinamik kontrol oluşturmayla ilgili bir sorun var sanırım. En basit haliyle kontrolleri yüklediğini Grid, Panel gibi konteyner üzerindeki tüm kontrolleri tek tek okuyup ID’si veya tipi uygun olanlara yakalayınca ona göre yönlendirme yapabilirsiniz. Örneğin ismi MainGrid olan Grid üzerindeki bir buttonu tıkladığımız düşünelim. Bu Grid üzerinde ister dinamik ister manual olarak MbTextBox kontrolünü eklediğimizi varsayalım.public Window1()
    {
    InitializeComponent();
    MbTextBox oTxt = new MbTextBox();
    oTxt.Width = 100;
    oTxt.Height = 100;
    oTxt.Text = "Örnek";
    MainGrid.Children.Add(oTxt);
    }
    private void button1_Click(object sender, RoutedEventArgs e)
    {
    foreach (UIElement elem in MainGrid.Children)
    {
    //Burada kontrolerin ID'sini veya tipine göre yönlendirme yapılabilşir.
    if (elem.GetType() == typeof(MbTextBox))
    {
    MessageBox.Show("MbTextBox türünde kontrol bulundu");
    ((MbTextBox)elem).ValidateControl();
    }
    }
    }

    Cevapla
  7. sinan

    Ornek icin teskurler.
    daha cok Delegates and Events kulanmak istedim ogrenmek icin.
    PropertyChangedCallback boyle bir yontemle imkanli degilmi?Sanirsam wpf tercubeniz iy.Wpf Exception & Errors Handling hakinda nasil bir ornek onerirsiniz?Hatalari guzel sekilde kulanciya gostermek UI.
    Log yapilmali.Bunu standart bir class ve xaml yapip her hatada cagirip kulanmak istiyorum.
    Error Handling in ASP.Net kulandigi gibi.
    slm

    Cevapla
  8. tayfun yılmaz

    ben bu olay yöneticisinde kodla birlikte döngü kullanarak buton oluşturuyorum formumda fakat ben bu döngü ie oluşturuduğum birden fazla butonu nasıl yönetbilrim bu olay tutucuyla bir örnek verebilirmisinZ..??

    Cevapla
  9. Ahmet Kaymaz Yazar

    Makalede custom control için bir örnek verilmiş. Button için de deklarasyon satırı hariç diğer tanımlamalar da verilmiştir. Oluşturduğunuz tüm Button’ların Click eventini aynı yordama bağlarsınız o yordam içerisinde Button ID’lerine bakarak veya Tag gibi bağımsız özelliğinin değerini okuyarak hangi Button’ın tıklandığını öğrenebilirsiniz. Tam olarak ne yapmak istediğinizi yazabilirseniz daha iyi yardımcı olabilirim.

    Cevapla
  10. gökay

    Sabahdan beri c#’da sınıf, nesne, property gibi konuları çalışıyorum hepsini bişekilde anladım fakat bu delegeler ve event olayını internette bulduğum her makaleyi okumaya çalışıyorum bir türlü kafam basmadı. Böyle bir duruma nerelerde gerek duyarız yada ne gerek var nerelerde kullanılıyor kafamda bişey oluşmadı bu yazıda da. :(

    Cevapla
  11. Ahmet Kaymaz Yazar

    Bu 3 makale delegate ve event yapılarına neden ihtiyaç duyulduğunu öğrenmek için yeterli olduğunu düşünüyordum. Belki de yeniden okuman veya başka kaynakları incelemen gerekebilir.

    Cevapla
  12. Asım Doğan NAMLI

    doğrusu çok teşekkür ederim c#’da delegadeleri nasıl kullanacağımı biliyordum vb.net’de olanınıda gördüm öğrenmiş oldum çok teşekkürler

    Cevapla
  13. Salih YÜCEL

    Selam;
    Öncelikle şöyle bir şey soracağım en azından elinizde böyle bir şey varmıdır acaba.
    Sistemde olan aktif olarak gezen kullanıcılara bir mesaj atmak istiyorum admin mesajı yazacak ve kullanıcılara gönder dediğinde kullanıcıların event ları çalışarak bir tane messagebox çıkacak böyle bir çalışma yaptınız mı
    Teşekkürler..

    Cevapla
  14. Ahmet Kaymaz Yazar

    Salih,böyle bir çalışma yapmadım. Ancak Web veya Windows olmasına bağlı olarak basit bir çözüm geliştirilebilir. Admin mesajını bir tabloya girer client uygulama da o kısa periyotlarla o tabloyu sorgular örneğin.

    Cevapla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.