سفارش‌های مایکروسافت برای استفاده‌ی کارآمد از DataGridView در دات نت

برای مشاهده‌ی مقاله‌ی انگلیسی اینجا کلیک کنید

DataGridView به گونه‌ای توسعه یافته تا بتواند حجم عظیمی از داده‌ها را مدیریت کند. با این حال در روبرویی با داده‌های حجیم، استفاده‌ی بهینه از این شیء برای پیشگیری از کاهش کارایی و افزایش مصرف حافظه ضروری است.

در این نوشته به موارد زیر که در این هدف ما را یاری می‌رسانند خواهیم پرداخت:

  • استفاده‌ی کارآمد از قالب‌بندی‌ها( Style ) برای سلول‌ها
  • استفاده‌ی کارآمد از منوهای میانبر
  • استفاده‌ی کارآمد از تغییر اندازه‌ی خودکار
  • به‌کارگیری کارآمد کلکسیون سلول‌ها، ردیف‌ها و ستون‌های انتخاب شده
  • به‌کارگیری ردیف‌های اشتراکی( Shared )
  • پیش‌گیری از حالت غیراشتراکی ردیف‌ها


چنانچه نیازهای کارآیی ویژه‌ای دارید، لازم است تا از حالت مجازی( Virtual Mode ) استفاده کنید. برای اطلاعات بیشتر اینجا کلیک کنید

استفاده‌ی کارآمد از قالب‌بندی‌ها برای سلول‌ها

هر «سلول»، «ردیف» و «ستون» قالب‌بندی‌های خاص خود را داراست. این قالب‌بندی‌ها در شیء DataGridViewCellStyle ذخیره می‌شوند. ایجاد این شیء برای تعداد زیادی از سلول‌ها، ردیف‌ها و ستون‌ها اثرهای منفی بر کارایی بر جای می‌گذارد. برای دوری کردن از این اثر بر کارایی نکته‌های زیر را رعایت کنید:

  • از تعیین قالب‌بندی انفرادی سلول‌ها و ردیف‌ها خودداری کنید. این قانون شامل ردیف اشاره‌شده توسط RowTemplate نیز می‌شود.هر ردیف Clone شده از ردیفی دیگر، کپی خود را از شیء DataGridViewCellStyle ایجاد خواهد کرد. برای بیشینه کردن مقیاس‌پذیری، قالب‌بندی‌ها را در سطح DataGridView مشخص کنید. برای نمونه به جای مقدار دهی به شیئی از نوع DataGridViewCell.Style، از DataGridView.DefaultCellStyle استفاده کنید.
  • چنانچه لازم است تا قالب‌بندی برخی از سلول‌ها با سایر سلول‌ها تفاوت داشته باشد، برای تمامی سلول‌های متفاوت از یک نمونه‌ی DataGridViewCellStyle بهره‌گیری کنید. به عبارت دیگر از مقداردهی مستقیم DataGridViewCellStyle بر روی سلول‌ها، ردیف‌ها و ستون‌ها خودداری کنید. با مراجعه به این صفحه می‌توانید نمونه کدی برای مدیریت قالب‌بندی پیش‌فرض DataGridView را مشاهده نمایید. همچنین با پاسخگویی به رخداد CellFormatting می‌توانید از کاهش کارایی هنگام مشخص کردن قالب‌بندی سلول‌ها پیشگیری کنید. برای مشاهده‌ی نمونه‌ی کد اینجا کلیک کنید.
  • هنگام تعیین قالب‌بندی برای سلول‌ها به جای DataGridViewCell.Style از DataGridViewCell.InheritedStyle استفاده کنید. دسترسی مستقیم به مشخصه‌ی Style سبب می‌شود نمونه‌ی جدیدی از DataGridViewCellStyle -در صورت عدم وجود- ایجاد شود. افزون بر آن ممکن است این شیء تمامی مشخصات قالب‌بندی را در خود جای نداده باشد و برخی از مشخصات را از ردیف و ستون خود به ارث ببرد. برای مشاهده‌ی اطلاعات بیشتر اینجا کلیک کنید.

استفاده‌ی کارآمد از منوهای میانبر

هر «سلول»، «ردیف» و «ستون» منوی میانبر خاص خود را داراست.منوهای میانبر در کنترل DataGridView توسط کنترل‌های ContextMenuStrip نمایندگی می‌شوند. همانگونه که در مورد قالب‌بندی گفته شد، تعیین منوی میانبر انفرادی برای سلول‌ها و ردیف‌ها اثرگذاری منفی در کارایی را به دنبال دارد. برای پیشگیری از این رخداد نکته‌های زیر را رعایت کنید

  • از ایجاد منوهای میانبر انفرادی برای سلول‌ها، ردیف‌ها و ستون‌ها خودداری کنید. این قانون شامل قالب‌های ردیف نیز می‌شود زیرا با Clone شدن ردیف‌ها در هنگام ایجاد ردیف‌های جدید، منوی میانبر نیز Clone خواهد شد. برای دستیابی به بیشترین کارایی تنها یک منوی میانبر برای کل شیء ایجاد و تخصیص دهید
  • در صورتی که لازم است تا منوهای میانبر متفاوتی برای سلول‌های مختلف به نمایش درآید، این کار را با پاسخگویی به رخدادهای CellContextMenuStripNeeded و RowContextMenuStripNeeded به انجام برسانید. به‌کارگیری این دو رخداد سبب می‌شود تا مدیریت نمایش منو بر عهده‌ی شما قرارگیرد و در نتیجه کارایی افزایش یابد.

استفاده‌ی کارآمد از تغییر اندازه‌ی خودکار

ردیف‌ها، ستون‌ها و سرآمدها( Headers ) می‌توانند به صورت خودکار تغییر اندازه دهند تا تمامی محتوای متنی آن‌ها قابل مشاهده باشد. برای محاسبه‌ی اندازه‌ی مورد نیاز لازم است تا DataGridView تمامی اطلاعات موجود را پیمایش و بررسی کند. این پیمایش در هنگام وجود حجم زیادی از داده‌ها می‌تواند عملیاتی زمان‌بر و سنگین باشد. برای پیشگیری از اثرهای منفی این پردازش نکته‌های زیر را رعایت کنید.

  • از تعیین مشخصه‌ی تعیین اندازه‌ی خودکار در هنگامی که با حجم زیادی از داده‌ها سروکار دارید، خودداری کنید. چنانچه از تعیین اندازه‌ی خودکار استفاده می‌کنید، مقدار آن را بر روی «محاسبه فقط برای داده‌های قابل مشاهده» تنظیم کنید. در «حالت مجازی» نیز از همین تنظیم بهره‌گیری کنید.
    • برای ردیف‌ها و ستون‌ها مقدار DataGridViewAutoSizeRowsMode، DataGridViewAutoSizeColumnsMode و DataGridViewAutoSizeColumnMode را روی DisplayedCells یا DisplayedCellsExceptHeaders تنظیم کنید.
    • برای سرآمد ردیف‌ها مقدار DataGridViewRowHeadersWidthSizeMode را روی AutoSizeToDisplayedHeaders یا AutoSizeToFirstHeader تنظیم کنید
  • برای دستیابی به مقیاس‌پذیری، بیشینه، تغییر اندازه‌ی خودکار را غیرفعال کنید و اندازه‌ها را با کدهای برنامه‌نویسی مدیریت کنید

برای اطلاعات بیشتر در مورد تنظیم‌های «تغییر اندازه‌ی خودکار» اینجا کلیک کنید.

به‌کارگیری کارآمد کلکسیون سلول‌ها، ردیف‌ها و ستون‌های انتخاب شده

کلکسیون SelectedCells در برخورد با مجموعه‌های بزرگ ناکارآمد عمل می‌کند. مجموعه‌های SelectedRows و SelectedColumns نیز هرچند کمتر، همین شرایط را دارا هستند. این تفاوت در ناکارآمدی به دلیل کمتر بودن تعداد ردیف‌ها و ستون‌ها در مقایسه با سلول‌ها است. برای پیشگیری از این کاهش کارایی، نکته‌های زیر را در نظر داشته باشید:

  • پیش از فراخوانی SelectedCells برای تعیین انتخاب شدن تمامی سلول‌ها، مقدار بازگشتی متد AreAllCellsSelected را بررسی کنید. به یاد داشته باشید که فراخوانی این تابع نیز سبب می‌شود ردیف‌ها به حالت غیراشتراکی در بیایند. برای دستیابی به اطلاعات بیشتر در این مورد بخش بعد را مطالعه کنید
  • برای محاسبه‌ی تعداد سلول‌های انتخاب شده، به جای بررسی مقدار Count از شیء System.Windows.Forms.DataGridViewSelectedCellCollection، تابع DataGridView.GetCellCount را فراخوانی کنید و مقدار DataGridViewElementStates.Selected را به آن بفرستید. به طور مشابه از دستورهای DataGridViewRowCollection.GetRowCount و DataGridViewColumnCollection.GetColumnCount برای به دست آوردن تعداد ردیف‌ها و ستون‌های انتخاب شده بهره‌گیری کنید
  • از انتخاب‌های بر پایه‌ی سلول خودداری کنید. در عوض نوع انتخاب را در DataGridView.SelectionMode را با DataGridViewSelectionMode.FullRowSelect یا DataGridViewSelectionMode.FullColumnSelect مقداردهی کنید.

به‌کارگیری ردیف‌های اشتراکی( Shared )

استفاده‌ی کارآمد از حافظه در DataGridView با استفاده‌ی اشتراکی از ردیف‌ها ممکن شده است. بیشترین اطلاعات ممکن در مورد نما و رفتار ردیف‌های DataGridView به اشتراک گذاشته می‌شود تا کارایی به بیشینه‌ی خود برسد.
استفاده‌ی اشتراکی از ردیف‌ها سبب کاهش مصرف حافظه می‌شود، با این حال امکان غیراشتراکی شدن ردیف‌ها بسیار زیاد است. برای نمونه هنگامی که کاربر مستقیما با یک سلول تعامل داشته باشد، ردیف متناظر با آن سلول غیراشتراکی خواهد شد. به دلیل اینکه این رخداد اجتناب ناپذیر است، رهنمودهای ارایه شده در این بخش تنها در نمایش حجم بزرگی از داده‌ها و هنگامی که کاربر به نسبت با بخش کوچکی از داده‌ها تعامل داشته باشد، کارساز است.
در Gridهایی که به منبع داده متصل( Bound ) نیستند، چنانچه سلولی محتوی مقدار باشد، ردیف متناظر با آن به اشتراک گذاشته نمی‌شود. هنگامی که DataGridView به منبع خارجی داده متصل باشد یا هنگامی که از حالت مجازی استفاده می‌کند و داده‌ها در خارج از شیء نگهداری می‌شوند و امکان استفاده‌ی اشتراکی از ردیف‌ها فراهم می‌شود.
یک ردیف تنها هنگامی می‌تواند به صورت اشتراکی مورد استفاده قرار گیرد که وضعیت تمامی سلول‌های آن بر اساس ردیف و ستون متناظر با سلول قابل محاسبه باشد. هنگامی که وضعیت یک سلول را تغییر می‌دهید، این امکان از بین می‌رود و ردیف از وضعیت اشتراکی خارج می‌شود.
برای مثال ردیف در حالت‌های زیر نمی‌تواند به صورت اشتراکی مورد استفاده قرار گیرد:

  • ردیف محتوی سلولی انتخاب شده باشد و ستون متناظر با آن سلول انتخاب شده نباشد
  • ردیف حاوی سلولی با مقدار ToolTipText یا ContextMenuStrip تنظیم شده
  • ردیف حاوی سلولی از نوع DataGridViewComboBoxCell و مشخصه‌ی Items تعیین شده

در حالت‌های متصل( Bound ) و مجازی( Virtual ) برای نمایش ToolTip و تعیین منوی میانبر می‌توانید به رخدادهای CellToolTipTextNeeded و CellContextMenuStripNeeded پاسخ دهید.
DataGridView به صورت پیش‌فرض تلاش می‌کند تا برای ردیف‌های اضافه شده به DataGridViewRowCollection از حالت اشتراکی استفاده کند. برای اطمینان بیشتر نکته‌های زیر را رعایت کنید:

  • از فراخوانی حالت Add(Object[])‎ از تابع Add و حالت Insert(Object[])‎ از دستور Insert خودداری کنید
  • اطمینان حاصل کنید که ردیف مشخص شده با DataGridView.RowTemplate در وضعیت‌های زیر قابل اشتراک است:
    • هنگام فراخوانی Add()‎ یا Add(Int32)‎ و یا Insert(Int32,Int32)‎
    • هنگام افزودن مقدار DataGridView.RowCount
    • هنگام مشخص کردن DataGridView.DataSource
  • اطمینان حاصل کنید که ردیف مشخص شده توسط پارامتر indexSource در فراخوانی دستورهای AddCopy، AddCopies، InsertCopy و InsertCopies از کلکسیون DataGridView.Rows قابل اشتراک است
  • اطمینان حاصل کنید که ردیف‌های مشخص شده در هنگام فراخوانی حالت Add(DataGridViewRow)‎ از Add، AddRange، حالت Insert(Int32,DataGridViewRow)‎ از Insert و تابع InsertRange از کلکسیون DataGridView.Rows قابل اشتراک هستند

برای بررسی اشتراکی بودن یک ردیف، با استفاده از DataGridViewRowCollection.SharedRow ارجاعی از ردیف را به دست آورید و خاصیت index آن را بررسی کنید. ردیف‌های اشتراکی همیشه indexی برابر «۱-» دارند.

پیش‌گیری از حالت غیراشتراکی ردیف‌ها

ردیف‌های اشتراکی بر اساس فعالیت‌های کاربر یا عملیات برنامه‌نویسی ممکن است غیراشتراکی شوند. برای پیشگیری از کاهش کارایی باید مانع این رخداد شوید. برای تشخیص زمان‌هایی که یک ردیف از حالت اشتراکی خارج می‌شود، می‌توانید از رخداد RowUnshared استفاده کنید. این رخداد می‌تواند در اشکال‌زدایی و مدیریت اشتراک ردیف‌ها مفید باشد.
برای پیشگیری از غیراشتراکی شدن ردیف‌ها نکته‌های زیر را رعایت کنید

  • از شمارش یا پیمایش ردیف‌ها با دستور ForEach خودداری کنید. به طور معمول نیاز به دسترسی مستقیم به ردیف‌ها وجود ندارد. توابع DataGridView که با ردیف‌ها تعامل می‌کنند، شماره‌ی ردیف‌ها را و نه ارجاعی به آن‌ها را می‌پذیرند. افزون بر این، رخدادهای مربوط به ردیف‌ها، مشخصات ردیف‌های مربوط را به عنوان پارامتر در اختیار شما می‌گذارند و از غیراشتراکی شدن ردیف‌ها پیشگیری می‌شود
  • برای دسترسی به ردیفی از DataGridView تابع DataGridViewRowCollection.SharedRow را با پارامتر شماره‌ی ردیف فراخوانی کنید. به یاد داشته باشید که تغییر دادن شیء بازگشت داده شده توسط این دستور، سبب می‌شود تا تمامی ردیف‌های مشترک با این ردیف نیز تغییر کنند. با این وجود ردیف‌های جدید به صورت اشتراکی ایجاد نمی‌شوند. بنابراین ردیف‌های جدید هیچ‌گاه همراه ردیف‌های قبلی تغییر نمی‌کنند. همین‌طور به یاد داشته باشید که ردیف‌های اشتراکی ممکن است منوهای میانبر متفاوتی داشته باشند. برای گرفتن منوی میانبر اصلی مرتبط با یک ردیف، دستور GetContextMenuStrip را با پارامتر شماره‌ی ردیف فراخوانی کنید. اگر برای گرفتن منو از مشخصه‌ی ContextMenuStrip ردیف اشتراکی استفاده کنید، منوی صحیح را دریافت نخواهید کرد
  • از پیمایش کلکسیون DataGridViewRow.Cells خودداری کنید. دسترسی مستقیم به یک سلول سبب غیراشتراکی شدن ردیف والد آن خواهد شد. رخدادهای مربوط به سلول‌ها، مشخصه‌های لازم را به تابع ارسال می‌کنند و از غیراشتراکی شدن ردیف‌ها پیشگیری می‌کنند. برای دسترسی به شماره‌ی ردیف و ستون سلول فعلی و حفظ ردیف‌های اشتراکی، از CurrentCellAddress استفاده کنید
  • وضعیت انتخاب را با گزینه‌ای غیر از حالت سلولی تنظیم کنید. مقدار DataGridView.SelectionMode را روی FullRowSelect یا FullColumnSelect قرار دهید.
  • پاسخ دادن به رخدادهای DataGridViewRowCollection.CollectionChanged و DataGridView.RowStateChanged نیز سبب غیر اشتراکی شدن ردیف‌ها می‌شوند. از فراخوانی توابع DataGridViewRowCollection.OnCollectionChanged و DataGridView.OnRowStateChanged نیز که سبب فعال‌شدن این رخدادها می‌شوند خودداری کنید
  • هنگامی که وضعیت DataGridView.SelectionMode بر روی FullColumnSelect، ColumnHeaderSelect، FullRowSelect و یا RowHeaderSelect تنظیم شده است، کلکسیون DataGridView.SelectedCells را مورد دسترسی قرار ندهید.
  • از فراخوانی DataGridView.AreAllCellsSelected خودداری کنید. این مشخصه ممکن است باعث غیراشتراکی شدن ردیف‌ها شود.
  • هنگامی که DataGridView.SelectionMode روی CellSelect تنظیم شده است از فراخوانی تابع DataGridView.SelectAll که سبب غیراشتراکی شدن تمامی ردیف‌ها می‌شود، خودداری کنید.
  • از غیرفعال کردن خصوصیت ReadOnly یا Selected یک سلول هنگامی که این مشخصه در ستون مورد نظر فعال است، خودداری کنید
  • از دسترسی به DataGridViewRowCollection.List خودداری کنید. این دستور تمامی ردیف‌ها را در وضعیت غیراشتراکی قرار می دهد
  • از فراخوانی حالت Sort(IComparer)‎ از دستور Sort که سبب می‌شود تمامی ردیف‌ها غیراشتراکی شوند، خودداری کنید
این نوشته در برنامه‌نویسی, دات نت ارسال و برچسب شده است. افزودن پیوند یکتا به علاقه‌مندی‌ها.

یک دیدگاه برای سفارش‌های مایکروسافت برای استفاده‌ی کارآمد از DataGridView در دات نت

  1. محسن می‌گوید:

    جناب ایرانی عزیز مقاله بسیار مفید وکارامدی بود . سپاسگذاریم

پاسخ دادن به محسن لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>