۱۳۸۹/۰۶/۲۲

مديريت رخدادهاي MouseLeftButtonDown و MouseLeftButtonUp در Silverlight


نياز بود تا بتوان رخدادهاي MouseLeftButtonDown و MouseLeftButtonUp يك TextBox را در Silverlight مديريت كرد. شايد عنوان كنيد كه خيلي ساده است! دو روال رخداد گردان مربوطه را اضافه كنيد و سپس تعاريف آن‌ها را در كدهاي XAML خود قيد نمائيد. اما واقعيت اين است كه كار نمي‌كند! نه؛ كار نمي‌كند! :)

مشكل از كجاست؟ پاسخي كه در MSDN در اين مورد آمده است به صورت زير مي‌باشد:

"Certain control classes (for example Button) provide control-specific handling for mouse events such as MouseLeftButtonDown. The control-specific handling typically involves handling the event at a class level rather than at the instance level, and marking the MouseLeftButtonDown event data's Handled value as true such that the event cannot be handled by instances of the control class, nor by other objects anywhere further along the event route. In the case of Button, the class design does this so that the Click event can be raised instead."


به عبارتي رخداد Click زحمت كشيده و رخدادهاي MouseLeftButtonDown و MouseLeftButtonUp را نيز handled معرفي مي‌كند و ديگر روال رخدادگردان شما فراخواني نخواهد شد (در WPF هم به همين صورت است) و موارد ذكر شده در visual tree يك TextBox منتشر نمي‌گردند.

راه حل چيست؟

حداقل دو راه حل وجود دارد:
الف) يك كنترل TextBox سفارشي را از كنترل TextBox اصلي بايد به ارث برد و رخدادهايي را كه توسط رخداد Click به صورت handled معرفي شده‌اند، unhandled كرد:

public class MyTextBox : TextBox
{
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
e.Handled = false;
}

protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
e.Handled = false;
}
}

ب) يا امكان گوش فرا دادن به رخدادهاي handled نيز ميسر است. فقط كافي است اين گوش فرادهنده را توسط متد AddHandler كه پارامتر آخر آن به true تنظيم شده است (رخدادهاي handled نيز لحاظ شوند)، معرفي كرد:

public MainPage()
{
InitializeComponent();
txt1.AddHandler(FrameworkElement.MouseLeftButtonDownEvent,
new MouseButtonEventHandler(txt1_MouseLeftButtonDown), true);
}
private void txt1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{

//do something
}