PDA

View Full Version : چگونه مي توان در يک متد ovveride شده،متدهاي همسان پدربزرگ و بالاتر رو فراخواني کرد



SMRAH1
شنبه 27 مهر 1387, 19:30 عصر
سلام

به برنامه زير توجه کنيد:


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
A a = new C();
a.Write();
}
}

class A
{
public virtual void Write()
{
Console.WriteLine("Class A");
}
}

class B : A
{
public override void Write()
{
Console.WriteLine("Class B");
}
}

class C : B
{
public override void Write()
{
Console.WriteLine("Class C");
base.Write();
}
}
}

خروجي اين برنامه به شکل :


Class C
Class B

است.بيشتر به متد Write کلاس C توجه کنيد.در اين متد با فراخواني متد Write از base عملا Write کلاس B فراخواني مي شود.حالا اگر بخواهيم در اين متد ،متد Write کلاس A را فراخواني کنيم،بايد چکار کنيم.به عبارت ديگر خط

base.Write();
را طوري تغيير دهيد که خروجي برنامه اين باشد:


Class C
Class A

در ضمن فرض کنيد که به پياده سازي کلاس هاي A و B دسترسي نداريم و فقط ميدانيم که B از A ارث مي برد و متد Write در کلاس A در B نيز باز نويسي شده است (مانند بالا).

ممنون

dark.lord
شنبه 27 مهر 1387, 21:22 عصر
تا آن جا که فکر می کنم نمی توان از طریق یک کلاس فرزند به کلاسی بالاتر از کلاسی که از آن مشتق شده رسید! به عبارتی راه مستقیم ندارد. به نوعی می توان با ساختن آبجکتی از B و ریختن آبجکت معرفی شده از C در آن و با استفاده از فراخوانی متد write از base به نتیجه ی مطلوب رسید. به هر صورت راه مستقیمی برای این کار نیست.

SMRAH1
یک شنبه 28 مهر 1387, 07:41 صبح
با توجه به اینکه در دیگر زبانها از جمله ++C و ++VC6 این دسترسی امکان پذیر بود،به نظرم رسید شاید راهی موجود باشه.
منتظر نظر دیگر دوستان هستم.

ممنون

Mehdi Asgari
دوشنبه 29 مهر 1387, 12:11 عصر
wow
این که به کد B دسترسی نداریم کار رو سخت می کنه.
اصولا ما تو C# نمی تونیم این کارو بکنیم (یعنی نیازی هم به انجام این کار نیست(
من کد شما رو کامپایل کردم. بعد کد MSIL حاصل رو نگاه انداختم ؛ این محدودیت از زبان C# هست . یعنی ما می تونیم توی خود IL کاری رو که شما می خواید بکنید. توی کد IL مربوط به متد Write کلاس C ، اینو نوشته:


.maxstack 8
IL_0000: nop
IL_0001: ldstr "Class C"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldarg.0
IL_000d: call instance void ConsoleApplication2.B::Write()
IL_0012: nop
IL_0013: ret

یعنی کامپایلر سی شارپ تشخیص داده که باید متد Write کلاس B فراخوانی بشه. من B رو کردم A و با ILAsm دوباره کامپایل کردم کد IL رو ، و جواب مدنظر رو گرفتم.
پ. ن: اگه خیلی براتون مهمه ، میتونید از همین روش استفاده کنید. یعنی یه patcher بنویسید که طبق الگویی که بهش دادی ، کد IL برنامه تون رو سرچ کنه و تغییراتی رو که میخواید اعمال کنه.
پ. ن 2: من سعی ام رو می کنم که تو اوقات بیکاریم از طریق Reflection کاری رو که میخواید بکنم (مطمئنم نیستم به جواب برسم)

SMRAH1
دوشنبه 29 مهر 1387, 17:35 عصر
سلام

از راه حل خلاقاته شما واقعا لذت بردم.:کف:

اگر این توی IL میشه پس منطقا باید توی #C هم بشه.

منتظر یک راه حل بهتر هستم.

ممنون
موفق و سربلند باشید

Mehdi Asgari
دوشنبه 29 مهر 1387, 20:01 عصر
اگر این توی IL میشه پس منطقا باید توی #C هم بشه.
با کدوم منطق ؟
هر کاری که توی سی شارپ میشه کرد ، توی MSIL هم میشه (این که خب اصلا بدیهیه) اما عکس این گزاره نادرسته.
مثلا: ما می تونیم با IL یه برنامه بنویسیم که Entry Point اون داخل یک کلاس نباشه (یک global function باشه) ، اما با سی شارپ نمی تونیم (چون یک زبان fully object oriented هست)
خیلی از این مثال ها میشه زد.
در کل در پلتفرم دات نت ، قدرت MSIL از همۀ زبون ها بیشتره. (البته منظورم انعطاف پذیریه. وگرنه به نظر من اگر چیزی در سی شارپ نیست ، از نظر طراحش لازم نبوده که باشه! )
شعار من: هر زبانی را بهر کاری ساختند

ghayegh
دوشنبه 29 مهر 1387, 20:53 عصر
با سلام
:لبخندساده:
من یک فایل برایتان فرستادم . ببینید آن چیزی که میخواستید ، بوده یا نه ؟
به هر حال اگر منظورتان چیز دیگری بوده ، بگوئید .

Mehdi Asgari
دوشنبه 29 مهر 1387, 22:06 عصر
قبول نیست!! اینطور که راحت شد.
کد شما در اصل اینه:


class Class1
{
public string A
{
get
{
return "AAAAAA";
}
}
public virtual string GGGGGGGGGG()
{
return this.A;
}
}
class Class2 :Class1
{
public override string GGGGGGGGGG()
{
return base.GGGGGGGGGG();
}
}
class Class3 : Class2
{
public override string GGGGGGGGGG()
{
return base.GGGGGGGGGG();
}
}
Class1 C1 = new Class3();
MessageBox.Show(C1.GGGGGGGGGG());

خب ، من فکر می کنم SMRAH1 (http://barnamenevis.org/forum/member.php?u=44567)فرض رو بر این میذاره که Class2 اینطوریه:


class Class2 :Class1
{

public string A
{
get
{
return "BBBBB";
}
}

public override string GGGGGGGGGG()
{
return this.A();
}
}

یعنی حالت generic تر.
شما یک حالت خاص رو در نظر گرفتید. (ما فرض می کنیم به کد A و B یا همون Class1 و Class2 دسترسی نداریم؛ پس نمی دونیم چی ممکنه تو این کلاس ها باشه)

SMRAH1
دوشنبه 29 مهر 1387, 22:13 عصر
سلام

نه دوست من! متد GGGGGGGGGG با توجه یه سلسه مراتب اقدام به دسترسی به متد پایه می کنه (یعنی متد کلاس پدر دخیل است).برای اینکه دقیقا منظورم را متوجه شوید،متد GGGGGGGGGG کلاس 2 را طوری تغییر دهی که هیچ ربطی به متد GGGGGGGGGG کلاس 1 نداشته باشد.حالا در متد GGGGGGGGGG کلاس 3 بخواهید متد کلاس 2 را لغو کرده ولی به متد کلاس 1 دسترسی داشته باشید.

afsharm
سه شنبه 30 مهر 1387, 09:51 صبح
من فکر می‌کنم که در سی شارپ بنا به این بوده که بعضی چیزهایی که پیچیدگی زیادی را ایجاد می‌کرده ار عمدا ساپورت نکنند پس در نتیجه احتمال پشتیبانی «فراخوانی متدهای همسان پدربزرگ و بالاتر» در سی شارپ خیلی نیست. در هر صورت پیشنهاد می‌کنم این سوال را در گروه زیر هم مطرح کنید. مطمئن هستم اونجا آدم‌های کنجکاو به این موضوع خیلی زیاد هستند و جواب خوبی خواهید گرفت:
http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/topics

ghayegh
سه شنبه 30 مهر 1387, 14:47 عصر
با سلام
:خجالت:
درست است که من خودم هم در کدی که برای رفع این مشکل نوشتم :


public override string GGGGGGGGGG()
{
return base.GGGGGGGGGG();
}

در متد Override ، از base استفاده کردم، ولی :
معنی اصلی Override ، لغو متد کلاس پایه در کلاس مشتق است . اما اینکه ما بیائیم و حالا به هر وسیله ای ، چه از طریق base و چه چیز دیگر ، بخواهیم به کلاس بالاتر دسترسی داشته باشیم ، پس خواسته ایم که از مفهوم Override استفاده نکنیم . خوب پس حالا که می خواهیم از Override استفاده نکنیم ، پس چرا داریم این کار را می کنیم ؟ منظور من این است که شما می خواهید خلاف آن کاربردی را که از مفهوم Override انتظار می رود ، پیاده سازی می کنید ( حتی اگر راهی برای این کار باشد )
خوب شما که می خواهید به متغیرهای کلاس پایه دسترسی داشته باشید ، چرا اینکار را نمی کنید ؟


class Class1
{
public string A
{
get
{
return "AAAAAA";
}
}
public string GGGGGGGGGG()
{
return this.A;
}
}



class Class2 :Class1
{
private string _B = string.Empty;
public string B
{
get
{
return "BBBBBB";
}
}
public string GGGGGGGGGG()
{
return this.B ;
}
}



class Class3 : Class2
{
private string _C = string.Empty;
public string C
{
get
{
return "CCCCCC";
}
}
public string GGGGGGGGGG()
{
return this.C;
}
}



private void Form1_Load(object sender, EventArgs e)
{
Class1 C1 = new Class3();
listBox1.Items.Add(((Class1)C1).GGGGGGGGGG());
listBox1.Items.Add(((Class2)C1).GGGGGGGGGG());
listBox1.Items.Add(((Class3 )C1).GGGGGGGGGG());
}

خروجی :


AAAAAA
BBBBBB
CCCCCC

SMRAH1
چهارشنبه 01 آبان 1387, 20:01 عصر
سلام


معنی اصلی Override ، لغو متد کلاس پایه در کلاس مشتق است
نه دوست من ،نیست! بلکه ممکن است برای توسعه باشد.یعنی کارکرد این کلاس را به طور کامل لازم ندارم و فقط در زمانهای خاصی نیاز به کارکرد جاری است.البته ممکن است که کارکرد پدربزرگ یا بالاتر را لازم داشته باشم (مشکل از همین جا ناشی می شود) برای نمونه اینجا (http://barnamenevis.org/forum/showthread.php?t=126260)رو ببنید که مجبور شدم کلا یک Event جدید (http://barnamenevis.org/forum/showpost.php?p=616314&postcount=27)بگذارم (اصلا این بحث باعث دوباره یاد این مشکل بیافتم و پست بدم).

در پست (http://barnamenevis.org/forum/showpost.php?p=617703&postcount=4)4 اشاره شد که می توان از IL استفاده کرد.آیا اصلا راهی برای استفاده از دستورات MSIL در #C وجود دارد (نوشتن قسمتی از کد به IL).

ممنون
موفق باشید

Mehdi Asgari
پنج شنبه 02 آبان 1387, 14:49 عصر
سلام
اولا از SMRAH1 یا مدیر مربوطه خواهش می کنم یه پست مخصوص Inline MSIL in C# (حالا هر با عنوان فارسی) ایجاد کنن که این یه مبحث جداست .
ثانیا از SMRAH1 بابت سوال قشنگش ممنون ، چون باعث شد کلی مطالعه کنم.
در اینجا (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=344904)و اینجا (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=92865)از Microsoft همچین درخواستی شده. جواب مایکروسافت هم درست و قانع کننده است. ببینید ، C# یک زبان high level و type safe (http://en.wikipedia.org/wiki/Type_safety) هست. همین که آقای Hejlsberg (http://en.wikipedia.org/wiki/Anders_Hejlsberg)امکان unsafe pointer (http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx) ها رو در زبان قرار دادن ، به نظر من کافیه. اگه بشه MSIL رو داخل C# نوشت ، کلا type safety زیر سوال میره (توی اولین خط C# Specification (http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/CSharp%20Language%20Specification.doc) اینطور نوشته شده:


C# (pronounced “See Sharp”) is a simple, modern, object-oriented, and type-safe programming language.

Mike Stall یه همچین کاری (http://blogs.msdn.com/jmstall/archive/2005/02/21/377806.aspx) رو با استفاده از preprocessor ها و post compilation (بدون تغییر کامپایلر) کرده که ایده ی جالبیه (ولی نمیشه هر کاری باهاش کرد و محدودیت هایی هم داره که خودش بهش اشاره کرده)
در اینجا (http://cs.hubfs.net/blogs/f_team/archive/2006/08/15/506.aspx)اشاره شده که F# قابلیت inline IL داره. (تو فصل 13 کتاب Foundations of F# (http://www.amazon.com/Foundations-F-Experts-Voice-Net/dp/1590597575) هم یه اشاره ای کرده)
راهکارهای من:
1- چیزایی رو که میخواید تو F# نوشته و اون رو در C# فراخوانی (یا استفاده کنید)
2- یک اسمبلی با C# و یکی دیگه با IL نوشته و دو تا رو با ILMerge (http://research.microsoft.com/~mbarnett/ILMerge.aspx)، ادغام کنید. (من تو یه پروژه می خواستم از X86 assembly استفاده کنم ، کد اسمبلی مورد نظر رو در C++ نوشته ، با Managed C++ ، پوشش (wrap) داده و در C# ازش استفاده کردم)
3- همون راه پست 4 (تغییر در کد IL و کامپایل مجدد)

(اینجا رو ببین: http://research.microsoft.com/projects/ilx/absil.aspx )

Mehdi Asgari
پنج شنبه 02 آبان 1387, 14:57 عصر
wow
اینو هم ببین (ایدۀ خوبیه ، خودت میتونی یکی برای نیاز شخصیت بسازی)
http://docs.taoframework.com/Tao.Platform.Windows/Tao.Platform.Windows.IlasmAttribute.html

(راستی ، میتونی از System.Reflection.Emit (http://msdn.microsoft.com/en-us/library/system.reflection.emit.aspx) هم استفاده کنی ها! مثلا یه اسمبلی با تمام ویژگی های مد نظرت ، On the fly ایجاد کنی)
اینم دو منبع خوب:
http://www.ddj.com/windows/184416570
http://www.codeproject.com/KB/cs/DynamicCodeGeneration2.aspx

در ضمن با توجه به نیاز هات فکر می کنم کتاب های زیر مناسب باشن برات (البته جسارته ، چون خودم یه تازه کارم (شکلک خجالت))
1- Professional .Net Framework 2.0 (http://www.amazon.com/Professional-NET-Framework-2-0-Programmer/dp/0764571354)نوشته ی Joe Duffy (فصل 14)
2- Inside Microsoft .Net IL Assembler (http://www.amazon.com/Inside-Microsoft-NET-IL-Assembler/dp/0735615470)نوشته ی Serge Lidin (. آقای Lidin طراح IL هست. )
3- Expert .Net 2.0 IL Assembler (http://www.amazon.com/Expert-NET-2-0-IL-Assembler/dp/1590596463/) بازم نوشته ی Lidin (ویرایش دوم کتاب قبل. این کتابو نخون. بخورش )
4- CLR Via C# (http://www.amazon.com/CLR-via-Second-Pro-Developer/dp/0735621632/) نوشته ی Jeffrey Richter (http://en.wikipedia.org/wiki/Jeffrey_Richter) (به نظر من هر کس میخواد حرفه ای تو دات نت برنامه نویسی کنه باید اینو بخونه. بهترین کتاب برنامه نویسی که تو عمرم خوندم)

اَرژنگ
شنبه 04 آبان 1387, 07:02 صبح
بعضی وقتها جواب درست این نیست که سوال را جواب بدهد بلکه چرا نباید به سوال جواب داد.
در طراحی شئیگرائی استفاده از متدهایه کلاسهایه پدربزرگ و یا بالاتر حتی اگر در زبان برنامه نویسی هم ساپورت شده باشد کار درستی نیست.
اگر یک مثال برایه حلش باید به این روش استفاده کرد ارائه بدید راه حل ارائه میدیم، ولی اولین اشکال این سوال این است که طراحی عجیب و غریب را ترویج میکند و همانطوری که یکی از دوستان اشاره کردند اگر هم شدنی باشد پیچیدگی زیادی برایه کد ایجاد میکند.

SMRAH1
شنبه 04 آبان 1387, 16:03 عصر
سلام

من با نظر شما در رابطه با

در طراحی شئیگرائی استفاده از متدهایه کلاسهایه پدربزرگ و یا بالاتر حتی اگر در زبان برنامه نویسی هم ساپورت شده باشد کار درستی نیست.
مخالفم.چون به همان مقدار که ممکن است متد پیاده شده کلاس پدر برای کار ما مناسب نباشد،و نیاز به پیاده سازی جدید باشد (نه فقط توسعه) ،کد پیاده شده در کلاس های پدر بزرگ و بالاتر می تواند کارایی را بالا برده و افزودگی و کد نویسی در برنامه را کاهش دهد.


ممنون
موفق باشید

اَرژنگ
شنبه 04 آبان 1387, 16:51 عصر
سلام

من با نظر شما در رابطه با

مخالفم.چون به همان مقدار که ممکن است متد پیاده شده کلاس پدر برای کار ما مناسب نباشد،و نیاز به پیاده سازی جدید باشد (نه فقط توسعه) ،کد پیاده شده در کلاس های پدر بزرگ و بالاتر می تواند کارایی را بالا برده و افزودگی و کد نویسی در برنامه را کاهش دهد.


ممنون
موفق باشید
با تشکر از نظرتان، ولی به این نکات توجه کنید:
۱. این نظر من نیست، من بیشتر پترنهایه برنامه نویسی شئگرائی را مطالعه کردم و به پترنی که به این خصوصیت احتیاج داشته باشد برنخوردم، دلیلش به نظر من احتیاج نداشتن به این روش دلیل ساپورت نشدنش است.
۲.دلیلی که دادید مثال عملی دارد؟ با اینکه در شکل تئوری دلیلتان درست است ولی در عمل جایی به دلیلی که گفتید میشه برخورد؟ اگر که داشتن این قابلیت در حالت عملی مورد نیاز است‌ یک مثال لازم است که استفاده از پترنهایه استاندارد برایه حلش کافی نیست را نشان بدهد.
۳.اگر فقط از نظر تئوری علاقه به دانستن این که این کار را چگونه انجام بدهید دارید، ساپورت نشدنش این روش را نمیتوانید زیره سوال ببرید، عوضش نحوه پیاده کردنش را میتوانید بپرسید.
۴.از لحاض منطقی، اگر کلاس قرار است که متد پدربزرگ و یا بالتر را صدا بزند، چرا به جایه اینکه از کلاس کنونی ارث میبره مستقیما از کلاس پدربرگش ارث نمیبرید؟ (اگر از کلاس پدر برزگش ارث ببره استفاده از base کافی است.). base به شکل دفالت از انکپسولیشن پدری استفاده میکند، چرا از یک کلاس پائئینتر ارث ببریم که ۲ تا کلاس بالاتر را صدا بزنیم؟

با اینکه این سوال از نظر تئوری جالب است ولی در واقعیت به احتیاج از این روش برنمیخوریم، پس نتیجتا یا از لحاض طراحی کاره اشتباهیست و یا اینکه روشهایه دیگری موجود هستند که این احتیاج را برطرف میکنند.

در ضمن :
"به همان مقدار که ممکن است متد پیاده شده کلاس پدر برای کار ما مناسب نباشد،و نیاز به پیاده سازی جدید باشد (نه فقط توسعه) ،کد پیاده شده در کلاس های پدر بزرگ و بالاتر می تواند کارایی را بالا برده و افزودگی و کد نویسی در برنامه را کاهش دهد." معنی ندارد، در کلاسهایه پدربزرگ و بالاتر از کلاسهایه فرزند کد کمتری پیاده میشه پس نتیجه گرفته شده درست نیست.

بعد از مقدار بیشتری مطالعه و جستجو به این نتیجه رسیدم که استفاده از متدهایه پدربزگ و یا بالاتر coupling (فارسیش را نمیدانم، لطفا عربی سرهم نکنید) کد را بیشتر میکند و استفاده ازش دلیل بر طراحی اشتباه است.

SMRAH1
شنبه 04 آبان 1387, 17:32 عصر
سلام

در مورد نمونه عملي،يکي در اينجا (http://barnamenevis.org/forum/showpost.php?p=616314&postcount=27)موجود است!در اين مورد نياز بود که کليد هاي UpوDawn صفحه کليد رو خوده کنترل پردازش نکنه ولي کاربر بتونه پردازش کنه.
خوب رويداد OnKeyDown رو که رونويسي کردم،ديدم اگر base اون رو فراخواني کنم،دوباره کنترل پدر اين کليد ها رو پردازش وجابجاي Selection انجام ميشه (که ما نمي خواستيم) ولي اگر هم فراخواني نکنم،رويداد KeyِDown کنترل تحريک نميشه.
در اين حال سه راه به نظرم رسيد! اول تحريک اين رويداد به شکل ديگر،مثلا با کدي کليد غير معتبر (منظور کدي که در صفحه کليد موجود نباشد - روش نامعقولي است) يا فراخواني مستقيم اين رويداد (که شايد ممکن باشد ولي حداقل من نتوانستم).روش دوم فراخواني متد OnKeyDown پدربزرگ بود که ياد نکته اي قديمي در همين زمينه افتادم و اين تاپيک ايجاد شد.و سوم اينکه (روشي که استفاده کردم) ،معرفي يک رويداد جديد به نام MyKeyDown که چون در همين کنترل معرفي شده،خودم مي توانم تحريکش کنم.
به نظر من اصولي ترين راه يا راه اول (فراخواني مستقيم رويداد) يا راه دوم است .به خصوص راه دوم چون ممکن است کلاسهاي پدربزرگ يا بالاتر -قبول دارم که اين در حد تئوريست- احتياج به درک اين کليد ها و عکس العمل مناسب داشته باشند.

از اینکه 'ساپورت نشدنش' به طور مستقیم رخ داده،اطمینان دارم (و بحث ایراد نیست بلکه سئوال برای درک بهتر مفاهیم است) ولی همانطور که خود شما هم تاکید کرده اید دنبال 'نحوه پیاده کردنش' (منظور غیر مستقیم) هستم یا اینکه راه حل جایگزینی (که احتمالا من نمی دانم) پیشنهاد شود.

در ضمن منظورم از "به همان مقدار که ممکن است متد پياده شده کلاس پدر براي کار ما مناسب نباشد،و نياز به پياده سازي جديد باشد (نه فقط توسعه) ،کد پياده شده در کلاس هاي پدر بزرگ و بالاتر مي تواند کارايي را بالا برده و افزودگي و کد نويسي در برنامه را کاهش دهد." کاملا در اين مثال مشخص است.به جاي معرفي يک کنترل که از Control ارث برد و تمام آن کار هايي که DataGridView مي کنم انجام دهد،فقط کافيست کمي در روال معمول اين کنترل دخل و تصرف کنيم و تمام!چرا بايد کلاس به اين بزرگي را پياده سازي کرد.

از توجه شما ممنونم
منتظر نظرتان هستم
موفق باشيد

اَرژنگ
دوشنبه 06 آبان 1387, 13:37 عصر
با سلام،
زمانی که با دلفی کار میکردم با یک مشکلی شبیه به همین برخورد کرده بودم، مشکل اصلی این است که کلیدهایه بالا و پائین هارد کد شدند و تنها روش تمیز درست کردن مشکلی که باهاش برخوردید داشتن اون دو کلید به شکل پروپرتی یا فیلد داخلی است که کلاسهایه پائینتر قابلیت عوض کردنشان را داشته باشند.
اگر دات نت سورس کدش مانند دلفی در دسترسی بود میشد که همان کلاس را پدربزگش ارث بری کنیم (به جایه اینکه از داتا گرید ویو ارث ببره) و ۲ تا کلید بالا و پائین را به شکل پروپرتی تعریف کنیم.
حالا که سورس دات نت در دسترسی نیست، مشکل تبدیل شده به همین سوالی که این توپیک را شروع کرد، و گفتن اینکه سوال درست نیست مشکل اصلی را حل نمیکنه.
مشکل اصلی پیاده شدن اینکه کلیدها باید به یک شکل استفاده بشند از طرف مایکروسافت است.
این لینک http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic62853.aspx
یکمقداری در مورد ۲ روش مختلف بحث میکند، ولی به نظر من را حل درست داشتن کد داتاگریدویو و پیاده کردن دوبارش به شکلی که قابلیت تعریف کردن دگمه‌هایه بالا و پائین را به استفاده کننده کنترل بده است.
یا اینکه داتا گرید ویو را خودمان را پیاده کنیم.