PDA

View Full Version : سوال: cancel كردن عمل اصلي يك event فاقد مشخصه cancel براي آرگومان ورودي e



parhamt
پنج شنبه 30 خرداد 1392, 10:36 صبح
سلام دوستان
فرض بگيريد توسط يك رويداد

bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
يك ركورد به ديتا گريد شما اضافه ميگردد حال شما در هنگام رويداد

bindingNavigatorAddNewItem_MouseDown(object sender, MouseEventArgs e)
متوجه شده ايد كه نبايد ركورد جديد به ديتا گريد اضافه شود و در حقيقت جلوي رويداد
bindingNavigatorAddNewItem_Click را ميخواهيد بگيريد .حال با توجه به اينكه ارگومان ورودي e در هر دو رويداد فاقد مشخصه cancel هست كه با true كردن ان جلوي وقوع رويداد را گرفت بايست چكار كرد.
با سپاس از وقتي كه ميگذاريد

ali_hojati_00
پنج شنبه 30 خرداد 1392, 11:40 صبح
شما میتونید با یک if و یک متغیر Bool این کار را به راحتی انجام بدید

parhamt
پنج شنبه 30 خرداد 1392, 12:05 عصر
با اين حلت شما ميتوانيد كد هاي خودتان در 2 event را كنترل كنيد ولي در نهايت ركورد به ديتا گريد اضافه ميشود.

ali_hojati_00
پنج شنبه 30 خرداد 1392, 12:23 عصر
اگر از مبحث threading استفاده کنید چطور ؟

parhamt
پنج شنبه 30 خرداد 1392, 12:38 عصر
از اين مبحث استفاده نكردم . ولي بيشتر دنبال نكته اي يا كدي خاص بودم كه شايد متوجه ان نشده باشم و دوستان متوجه شده باشند كه بطور كلي بتوان براي رويدادهايي كه فاقد e.cancel هستند فكري كرد تا بتوان به نوعي اشتباه كاربر مثل كليك هاي بيمورد دكمه bindingNavigatorAddNewItem را خنثي نمود.

llMMDll
پنج شنبه 30 خرداد 1392, 13:54 عصر
bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{
//.....
}
public event CancelEventHandler EventTest = delegate { };
private void bindingNavigatorAddNewItem_MouseDown(object sender, MouseEventArgs e)
{
CancelEventArgs cea = new CancelEventArgs();
EventTest(this, cea);
if (shart cancel shodan)
{cea.Cancel=True;}
if (cea.Cancel)
{
// agar cancel shod anjam bede
}
else
{
// agar cancel nashod ino anjam bede
}
}

parhamt
پنج شنبه 30 خرداد 1392, 23:40 عصر
سلام llMMDll عزيز
كد شما متاسفانه جلوي فعال شدن رويداد bindingNavigatorAddNewItem_Click را نميگيرد و اگر شما كد فوق را در برنامه قرار دهيد بدون اينكه كد ديگري در اين دو رويداد قرار گيرد وبدون شرط ها كلاً
cea.Cancel=True را در نظر بگيريد باز پس از رويداد bindingNavigatorAddNewItem_MouseDown بصورت خودكار رويداد bindingNavigatorAddNewItem_Click فراحواني و ركورد جديد به ديتا گريد اضافه ميگردد

llMMDll
جمعه 31 خرداد 1392, 02:13 صبح
کد رو چک کردم شما درست می گفتید بلافاصله اجرا می شد

حال برای اینکه اجرا نشود می بایست 1 وقفه بندازید تا آن عمل صورت نگیرد و عمل کنسل شدن کامل تحقق پیدا کند کد زیر را وارد کنید


bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{
//.....
}
private void bindingNavigatorAddNewItem_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show(".....");
}


منتظر پاسخ شما هستم

parhamt
جمعه 31 خرداد 1392, 10:49 صبح
سلام llMMDll عزيز
ترفند شما كارساز است و با توجه به اينكه من مي خواهم به كاربر پيام بدهم هيچ مشكلي نيست.لطفاً اگر راه ديگري به نظرتان رسيد كه بتوان بدون پيغام دادن وقفه ايجاد كرد ويا اينگونه موارد را بدون وقفه مديريت نمود بفرماييد.
با سپاس فراوان از وقتي كه گذاشتيد.

gwbasic
جمعه 31 خرداد 1392, 21:18 عصر
متاسفانه BindingNavigator فقط رویداد AddNewItem دارد و رویدادی مثل AddingNewItem ندارد بنابراین شما جلوی عمل اضافه شدن را نمی تونید بگیرید. یک راه می تونه این باشه که کنترل AddnewItem‌ رو از لیست کنترل هایی که تحت مدیریت BindingNavigator هست، خارج کنید و عمل درج رو به صورت دستی به BindingSource مربوطه اعمال کنید.
برای این کار می بایست پراپرتی AddNewItem‌ مربوط به BindingNavigator را خالی کنید و سپس در رویداد کلیک کنترل AddNewItem خودتون یک نمونه از مدلی که به BindingSource‌ ، بایند کردین رو new‌ و به BindingSource اضافه کنید. در این رویداد دیگه مدیریت اضافه کردن یا نکردن دست شماست

parhamt
جمعه 31 خرداد 1392, 21:35 عصر
سلام بر شما gwbasic عزيز
از راهنمايي شما سپاسگزارم و راهي را كه فرموديد مد نظر قرار خواهم داد ولي مايل بودم با توجه به مدت زمان زيادي كه براي اين مبحث به ويژه در سايت هاي خارجي صرف كردم فردي مثل شما مرا مطمئن كند كه اشتباه نكرده ام و اساساً خود المان ضعف دارد.
با سپاس فراوان از شما

tooraj_azizi_1035
جمعه 31 خرداد 1392, 23:10 عصر
از متد CancelEdit شیء BindingSource تون استفاده کنید.

parhamt
شنبه 01 تیر 1392, 00:03 صبح
سلام بر شما tooraj_azizi_1035
اين متد به تنهايي نميتواند جلوي اضافه شدن ركورد را بگيرد.تنها راه همانطور كه llMMDll عزيز گفتند با يك وقفه همراه گردد مثلا يك messagebox .جالب انكه اگر شما به صورت trace هم وارد رويداد bindingNavigatorAddNewItem_MouseDown
شويد و از متد CancelEdit شیء BindingSource استفاده كنيد جلوي درج ركورد جديد گرفته ميشود و ظاهراً وقفه لازم با trace ايجاد ميشود ولي اگر بدون trace يا messagebox عمل كنيم ركورد اضافه ميشود.
سپاسگزار

mz6488
شنبه 01 تیر 1392, 08:08 صبح
سلام.از دستورات زیر استفاده کن


personBindingSource.EndEdit();
personDataset.RejectChanges();




به جای person باید از آبجکتی که تو پروژت هست باید استفاده کنی.

parhamt
شنبه 01 تیر 1392, 08:40 صبح
سلام mz6488 عزيز
كد

personDataset.RejectChanges();
را نسبت به كد دوست عزيز (tooraj_azizi_1035) شما اضافه نموده بوديد كه تست كردم ولي متاسفانه جلوي درج ركورد جديد را نميگيرد.
با سپاس از شما

parhamt
شنبه 01 تیر 1392, 08:41 صبح
سلام mz6488 عزيز
كد

personDataset.RejectChanges();
را نسبت به كد دوست عزيز (tooraj_azizi_1035) شما اضافه نموده بوديد كه تست كردم ولي متاسفانه جلوي درج ركورد جديد را نميگيرد.
با سپاس از شما

mz6488
شنبه 01 تیر 1392, 10:42 صبح
سلام mz6488 عزيز
كد

personDataset.RejectChanges();
را نسبت به كد دوست عزيز (tooraj_azizi_1035) شما اضافه نموده بوديد كه تست كردم ولي متاسفانه جلوي درج ركورد جديد را نميگيرد.
با سپاس از شما

شرمنده.کد رو اشتباه نوشتم!!!

personBindingSource.CancelEdit();
personDataset.RejectChanges();

parhamt
شنبه 01 تیر 1392, 11:56 صبح
سلام mz6488 عزيز
من متوجه منظور شما همان بار اول شده بودم و مطابق همين كد جديدي كه داديد عمل كردم كه متاسفانه جلوي درج ركورد را نميگيرد.
سپاسگزارم

mz6488
شنبه 01 تیر 1392, 12:09 عصر
خواهش میکنم

tooraj_azizi_1035
شنبه 01 تیر 1392, 12:35 عصر
عذر می خوام کدم رو تست نکرده بودم اینو تست کردم برای حذف آخرین رکورد می تونه استفاده بشه چون آخرین رکورد رکوردی هست که درج شده:

myBindingSource.Remove(myBindingSource.List.OfType<object>().Last());
کد بالا وقتی System.Linq رو اضافه می کنید کار میکنه البته می تونستید ردیف آخر جدولتون رو حذف کنید:
myDataTable.Rows.OfType<DataRow>().Last().Delete();

parhamt
شنبه 01 تیر 1392, 20:32 عصر
سلام و درود بر شما tooraj_azizi_1035
كد اول شما را امتحان كردم. عالي بود با حالات مختلف BindingSource.Remove كار كردم ولي مشكل ان بود كه هنوز ركورد تثبيت نشده بود كه از current يا شماره آخرين ركورد بتوان استفاده نمود.
بسيار آموختم
با سپاس فراوان از شما و بقيه بزرگواران

parhamt
یک شنبه 02 تیر 1392, 00:08 صبح
سلام خدمت tooraj_azizi_1035 عزيز
مشكلي در كد اول شما همانند كد هايي كه خود من ذكر كردم (BndingSource.RemoveCurrent) وجود دارد كه من بعلت خالي بودن ديتا گريدم در ابتداي كار متوجه نشدم .مشكل انجاست كه كد شما يا همين كدي كه نوشتم عمل حذف ركورد را از آخر BindingSource انجام ميدهند ولي چون هنوز رويداد bindingNavigatorAddNewItem_Click كامل نشده در حقيقت خط پر اخر را خالي ميكند و ركورد جديد را نيز در انتها به ديتا گريد اضافه ميكند و عملاً كار غلط است.
سپاسگزارم

llMMDll
یک شنبه 02 تیر 1392, 00:35 صبح
امیدوارم این هم به دردتون بخوره

میتونید Focus رو به کنترل دیگری منتقل کنید مثل Lable



bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{
//.....
}
private void bindingNavigatorAddNewItem_MouseDown(object sender, MouseEventArgs e)
{
label1.Focus();
}

parhamt
یک شنبه 02 تیر 1392, 01:09 صبح
با سلام خدمت شما llMMDll
كد پيشنهادي شما را به صورت تكي وبه همراه BindingSource.CancelEdit با فكوس بر روي يك دكمه امتحان كردم .متاسفانه وقفه لازم را ايجاد نميكند و خط جديد درج ميگردد.تا اينجا بهترين حالت اگر بتوان به كاربر يك پيغام خطاي مناسب داد همان استفاده از BindingSource.CancelEdit به همراه پيغام خطاء است و اگر نتوان پيغام داد من فعلا با سنجيدن وضعيت در رويداد bindingNavigatorAddNewItem_MouseEnter دكمه درج navigator را غير
فعال ميكنم كه البته برگرداندن اين دكمه به حالت فعال بخاطر اينكه خودش ديگر رويداد پذير نيست و حالات ممكن كارپر دردسري است.
متشكرم

parhamt
دوشنبه 03 تیر 1392, 10:21 صبح
سلام خدمت همه دوستان
اين را در نطر داشته باشيد كه اگر در رويداد bindingNavigatorAddNewItem_MouseDown حتي بدون BindingSource.CancelEdit هم پيغام خطا بدهيم جلوي اضافه شدن ركورد جديد گرفته ميشود كه اين يكي ديگه خيلي جالبه چون اگر شما به دليلي غير از وجود خطا لازم باشد پيغام بدهيد مجبور هستيد افزودن ركورد را خود مديريت كنيد.
موفق باشيد

gwbasic
دوشنبه 03 تیر 1392, 13:13 عصر
برنامه نویس در کنار تفکر کردن در مورد حل یک مسئله باید به اصول برنامه نویسی، روش درست کدنویسی فکر کند. چراکه این راه حل در آینده ممکن است توسط ما و افراد دیگر تیم گسترش داده شود و در صورت پیچیده و ناخوانا بودن وقت و انرژی زیادی از ما یا دیگران خواهد گرفت. بنابراین هیچ وقت دنبال کلک و راه حل نصفه نیمه نباشید. هیچ وقت نگید "خوب اینجا یه if می ذارم مشکل حله! " هر بخش از کد شما باید وظیفه ای مشخص داشته باشد و آن را به درستی انجام دهد. نباید بخش دیگری جور این بخش شما را بکشد... .

خوب از این داستان بگذریم. چیزی که واضح هست اینه که BindingNavigator و BindingSource جواب برخی نیازهای ما رو می دن ولی معماریشون طوری نیست که همه نیاز های ما رو براورده کنند. پس بهتره جاهایی که مشکل هست نخوایم بقول معروف زور چپون مشکلو حل کنیم، حالا راه حل درست چیه؟

BindingNavigator رو بازنویسی کنیم و مشکلات مربوطه رو برطرف کنیم که البته این کار تقریبا نشدنی هست چون اصولا این کامپوننت معماری درستی نداره که به ما امکان بسط و توسعه قابلیت های اون رو بده مثلا برای حل مشکل اعتبار سنجی قبل یا بعد از اتمام اضافه یا حذف یک آیتم کافی بود که دو متد OnAddNew و OnDelete‌ رو بازنویسی می کردیم اما متاسفانه این دو متد private ‌هستن و ما نمی تونیم اینها رو باز نویسی کنیم ... .

پس چه کنیم؟ همون راهی که پیشنهاد کردم از برخی قابلیت های خوب این کنترل استفاده کنیم و بقیه رو خودمون مدیریت می کنیم. کنترل های add و delete‌ رو از مدیریت BindingNavigator خارج می کنیم و خودمون مدیریت کنیم.

شاید بپرسین کار سختی هست ولی اصلا اینطور نیست هنگام اضافه کردن یک item‌ کاری که BindingNavigator انجام می ده اینه که متد bindingSource.AddNew رو صدا می زنه و هنگام حذف bindingSource.RemoveCurrent رو فراخوانی می کنه پس کافیه در کلیک دکمه Add‌ یا Delete در bindingNavigator مان از همین دو متد استفاده کنیم با این تفاوت که منطق مورد نیازمان را در این متد اضافه می کنیم. بطور مثال در هنگام delete‌ اول سوال کنیم که "آیا می خواین این آیتم حذف شود یا خیر؟" به این شکل کدمان پیچیدگی خواصی نداره و کار اضافه ای هم انجام نمی شه. مثلا اینکه اجازه بدیم بی مورد BindingNavigator آیتمی اضافه کنه و ما در جای دیگه ای اونو حذف کنیم یا اینکه پس از اینکه آیتم ما توسط BindingNavigator حذف شد به کاربر بگیم که شرمنده دیگه خودت کلیک کردی منم مامورم و معذور... حذف شد :)

امیدوارم که دیگه وقت و انرژی خودتون رو صرف این کامپوننت نکنید چراکه همانطور که گفتم این کامپوننت جوابگوی برخی از نیازهای ما هست