آموزش سی شارپ

آموزش سی شارپ

آموزش برنامه نویسی از مبتدی تا پیشرفته
آموزش سی شارپ

آموزش سی شارپ

آموزش برنامه نویسی از مبتدی تا پیشرفته

آموزش سی شارپ

کدهای مربوط به یک Grid در #C

ارسال شده توسط administrator
25. می 2010 02:29

clip_image002

مقدمه

SourceGrid یک کنترل windows form است که کلاً در c# نوشته می شود، هدف من ایجاد یک grid ساده اما انعطاف پذیر جهت استفاده در همه مواردی است که برای نمایش یا تغییر داده ها در یک table format لازم است. کنترلهای زیادی از این نوع در دسترس هستند، اما معمولاً سنگین هستند و به سختی customize می شوند، یا با .NET سازگار نیستند. به نظر من Microsoft DataGridخیلی DataSet گرا است، و بنابراین نتایج معمولاً برای استفاده در مواردی که source data، یک DataSet نیست و به اندازه کافی قابل customize نیست، پیچیده می شوند.

این کنترل توسط با Microsoft Framework. NET 1.1، و reference the assembly SourceLibrary.dll 1.2.0.0، compile می شود؛ این، یک library کوچک با کاربرد عادی است. جهت استفاده از SourceGrid، داشتن Visual Studio.NET 2003 یا یک محیط development سازگار، لازم است.

در این مقاله می خواهم چشم اندازی از استفاده و کاربرد کنترل SourceGrid ارایه کنم، جهت جزییات بیشتر در مورد کلاسها، propertyها، یا متدها، می توانید از documentation کمک بگیرید.

استفاده از SourceGrid

در assembly SourceGrid2.dll حاضر هستند، 2 کنترل که می توان درجعبه ابزار Visual Studio قرار داد و در هر formی استفاده کرد:

GridVirtual – یک گرید از سلولهای مجازی (ICellVirtual).

Grid – یک گرید از سلولهای واقعی ( ICell).

بنابراین دو تفاوت اساسی وجود دارد: سلولهای مجازی و سلولهای واقعی.

سلولهای مجازی، سلولهایی هستند که ظاهر و رفتار سلول را تعیین می کنند، اما شامل value نمی شوند، سلولهای واقعی، دارای همان ویژگی های سلولهای مجازی هستند، اما value را هم در بر می گیرند. بنابراین مربوط به موقعیت معینی از grid می شوند.

clip_image003

هر سلول از سه بخش اصلی تشکیل شده است:

DataModel: DataModel، کلاسی است که valueی سلول را مدیریت می کند. Valueی سلول را به یک string برای نمایش بصری (visual representation) تبدیل می کند، editor سلول را ایجاد می کند و valueهای insert شده را اعتبار سنجی می کند.

VisualModel: VisualModel، کلاسی است که سلول را ترسیم می کند و دربر گیرنده propertyهای visual است.

BehaviorModel: BehaviorModel کلاسی است که رفتار سلول را تعیین می کند.

این subdivision، انعظاف و قابلیت استفاده مجدد به code می دهد، و در زمان صرفه جویی می کند. برای موارد رایج تر، کلاسهایی وجود دارند که قبلاً مدیریت و پیکربندی شده اند، اما با خطهای کم کد، ایجاد سلولهای customize شده، ممکن است.

Grid

اگر می خواهید انعطاف و سادگی بیشترین را بدون سلولهای زیاد می خواهید، کنترل Grid ایده آل است. در واقع، در این کنترل، همه سلولها توسط یک کلاس .NET ارایه می شود و بنابراین مقدار معینی از منابع را اشغال می کنند. به علاوه، این تنها gridیی است که ویژگی های RowSpan و ColumnSpan را ساپورت می کند.

بعد از insert کردن کنترل در فرم، می توانیم نوشتن کدمان را جهت استفاده از grid در رویداد Load فرم شروع کنیم:

grid1.Redim(2, 2);
grid1[0,0] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 0,0");
grid1[1,0] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 1,0");
grid1[0,1] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 0,1");
grid1[1,1] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 1,1");

کد قبلی یک جدول با 2 خط و دو ستون ایجاد می کند (متد Redim) و همه positionها را با یک سلول اشغال می کند. از از فضای اسمی SourceGrid2.Cells.Real استفاده کرده ام که در همه سلولهای واقعی وجود دارد.

همه سلولها، تمامی خصوصیات لازم نمایش را دارند، مثلاً جهت تغییر رنگ پیش زمینه سلول می توانیم بنویسیم:

SourceGrid2.Cells.Real.Cell l_Cell = new SourceGrid2.Cells.Real.Cell(
"Custom back color");
l_Cell.BackColor = Color.LightGreen;
grid1[0,0] = l_Cell;

اینها، خصوصیات ظاهری یک سلول هستند: BackColor، ForeColor، Border, Font، TextAlignment، WordWrap.

حالا سعی می کنیم یک grid کلی با header، و automatic sort، و resize ستونها با ماوس، رشته (string)، و ویرایشگر DateTime و یک checkbox ایجاد کنیم.

grid1.BorderStyle = BorderStyle.FixedSingle;
grid1.ColumnsCount = 3;
grid1.FixedRows = 1;
grid1.Rows.Insert(0);
grid1[0,0] = new SourceGrid2.Cells.Real.ColumnHeader("String");
grid1[0,1] = new SourceGrid2.Cells.Real.ColumnHeader("DateTime");
grid1[0,2] = new SourceGrid2.Cells.Real.ColumnHeader("CheckBox");
for (int r = 1; r < 10; r++)
{
grid1.Rows.Insert(r);
grid1[r,0] = new SourceGrid2.Cells.Real.Cell("Hello "
+ r.ToString(), typeof(string));
grid1[r,1] = new SourceGrid2.Cells.Real.Cell(
DateTime.Today, typeof(DateTime));
grid1[r,2] = new SourceGrid2.Cells.Real.CheckBox(true);
}
grid1.AutoSizeAll();

در کد قبلی، من grid border، تعداد ستونها، تعداد ردیفهای ثابت را تنظیم و اولین ردیف header را ایجاد کرده ام. برای header، من از یک سلول ColumnHeader استفاده کرده ام. کلاس Cell به طور اتوماتیک، یک editor مناسب برای نوع داده ای معین، ایجاد می کند. برای آخرین ستون، من از یک سلول CheckBox استفاده کرده ام که یک checkbox را مستقیماً روی سلول نمایش میدهد. این فرم باید شبیه figure زیر باشد:

clip_image001

GridVirtual

کنترل GridVirtual، وقتی نمایش سلولهای زیاد واجب است و وقتی ساختاری

این نوع grid، دارای همان ویژگی های کنترل Grid است، به غیر از automatic sort (زیرا grid نمی تواند هیچ ساختار داده ای را بدون کپی کردن محتویاتش مرتب کند) و ویژگی RowSpan و ColumnSpan که اجازه span کردن یک سلول را در سلولهای مجاور دیگر می دهد. عیب دیگر این است که ایجاد یک grid مجازی کمی مشکل است.

مفهوم اصلی یک grid مجازی این است که سلولها، valueها را دربر نمی گیرند، اما value را در یک ساختار داده ای خارجی می خوانند و می نویسند. این ایده با یک کلاس انتزاعی CellVirtual اجرا می شود که در آن تعریف دوباره متدهای GetValue و SetValue لازم هستند.

جهت استفاده از GridVirtual، ایجاد یک کلاس که از CellVirtual مشتق شده و شخصی کردن reading با استفاده از منبع داده انتخاب شده، واجب است. معمولاً بهتر است یک کنترل که از GridVirtual مشتق می شود نیز ایجاد کنیم تا انعطاف بیشتر و کدی solid تر داشته باشیم که متد GetCell را override می کند. اگر مایل باشید، می توانید مستقیماً از کنترل GridVirtual و رویداد GettingCell استفاده کنید. هدف متد GetCell و رویداد GettingCell، بازگرداندن سلول انتخابی است. این کار انعطاف زیادی را ایجاد می کند، زیرا می توانید برای یک نوع داده ای معین، هر ICellVirtual را بازگردانید؛ مثلاً می توانید سلول یک type header را وقتی که ردیف 0 است، بازگردانید.

در مثال زیر، من یک grid مجازی ایجاد می کنم که valueها را در یک آرایه می نویسد. ابتدا، کنترل GridVirtual را در یک فرم insert می کنم، سپس این کد را که کلاس مجازی ما را تعریف می کند، می نویسم:

public class CellStringArray : SourceGrid2.Cells.Virtual.CellVirtual
{
private string[,] m_Array;
public CellStringArray(string[,] p_Array):base(typeof(string))
{
m_Array = p_Array;
}
public override object GetValue(SourceGrid2.Position p_Position)
{
return m_Array[p_Position.Row, p_Position.Column];
}
public override void SetValue(SourceGrid2.Position p_Position,
object p_Value)
{
m_Array[p_Position.Row, p_Position.Column] = (string)p_Value;
OnValueChanged(new SourceGrid2.PositionEventArgs(p_Position, this));
}
}

با کد قبلی، من یک سلول مجازی با یک editor از نوع string ایجاد کردم که valueها را در یک آرایه، که در constructor معین شده، می خواند و می نویسد. بعد از فراخوانی متد SetValue، باید متد OnValueChangedرا فرابخوانیم تا grid را از update کردن این سلول آگاه کنیم.

من کد زیر را در در رویداد Load در Form قرار داده ام:

private void frmSample15_Load(object sender, System.EventArgs e)
{
gridVirtual1.GettingCell += new SourceGrid2.PositionEventHandler(
gridVirtual1_GettingCell);
gridVirtual1.Redim(1000,1000);
string[,] l_Array = new string[gridVirtual1.RowsCount,
gridVirtual1.ColumnsCount];
m_CellStringArray = new CellStringArray(l_Array);
m_CellStringArray.BindToGrid(gridVirtual1);
}

من یک event handler به رویداد GettingCell اضافه کرده ام، و grid وآرایه را با 1000 ردیف و 1000 ستون ایجاد کردم، سپس مثال جدیدی از سلول قبلی ایجاد کردم و با استفاده از متد BindToGrid، سلول را به grid لینک کردم. یک سلول واحد ایجاد کردم که برای هر موقعیت matrix استفاده خواهد شد. فراخوانی متد BindToGrid روی سلولهایی که می خواهیم در یک grid مجازی استفاده کنیم، همیشه لازم است.

جهت اتمام کار، باید متد GettingCell را بنویسیم و متغیر را برای سلول تعریف کنیم:

private CellStringArray m_CellStringArray;
private void gridVirtual1_GettingCell(object sender,
SourceGrid2.PositionEventArgs e)
{
e.Cell = m_CellStringArray;
}

نتیجه حاصله باید شبیه تصویر زیر باشد:

clip_image001[5]

VisualModel

فضای نامی: SourceGrid2.VisualModels

همه سلولها یک property دارند که یک رابط type IvisualModel را باز می گرداند. سلول از این رابط (Interface) جهت ترسیم و سفارشی کردن ویژگی های ظاهری (visual properties) سلول استفاده می کند.

هدف VisualModel، جدا سازی کد drawing از بقیه کد است و اجازه به اشتراک گذاشتن همان مدل visual بین سلولهای بیشتری است. در حقیقت،می توان از همان مثال VisualModel روی سلولهای بیشتری به طور همزمان استفاده کرد تا منابع سیستم را بهینه کند. کلاسهای پیش فرض VisualModel، فقط خواندنی (read-only) هستند، اما یک متد Clone، که به شما اجازه می دهد نمونه های همسانی از همان مدل را ایجاد کنید، در اختیار هر VisualModel قرار می گیرد.

در زیر کلاسهای پیش فرض VisualModel در namespace آورده شده است.

  • SourceGrid2.VisualModels.Common: برای سلولهای کلاسیک استفاده می شود. در این مدل، شما می توانید رنگها، فونت، borderها و propertyهای زیاد دیگری را customize کنید.
  • SourceGrid2.VisualModels.CheckBox*: برای سلولهای checkbox style استفاده می شود. می توان checkbox را انتخاب، و غیر فعال (disable) کرد و می تواند یک caption داشته باشد.
  • SourceGrid2.VisualModels.MultiImages: اجازه ترسیم بیشتر از یک image را در یک سلول می دهد.

VisualModel که با ستاره مشخص شده است، نیاز به یک رابط (interface) دارد که درست کار کند، مثلاً مدل CheckBox، نیاز به یک سلول دارد تا رابط ICellCheckBox را ساپورت کند.

هر یک از این کلاسها شامل یک یا چند property ثابت با چند نمونه فقط خواندنی است که براحتی قابل استفاده هستند.

· SourceGrid2.VisualModels.Common.Default

· SourceGrid2.VisualModels.Common.LinkStyle

· SourceGrid2.VisualModels.CheckBox.Default

· SourceGrid2.VisualModels.CheckBox.MiddleLeftAlign

· SourceGrid2.VisualModels.Header.Default

· SourceGrid2.VisualModels.Header.ColumnHeader

· SourceGrid2.VisualModels.Header.RowHeader

این کد چگونگی تخصیص دادن همان VisualModel را به سلولهای بیشتری که قبلاً ایجاد شده اند، نشان می دهد و سپس بعضی از propertyها را تغییر می دهد:

SourceGrid2.VisualModels.Common l_SharedVisualModel = 
new SourceGrid2.VisualModels.Common();
grid1[0,0].VisualModel = l_SharedVisualModel;
grid1[1,0].VisualModel = l_SharedVisualModel;
grid1[2,0].VisualModel = l_SharedVisualModel;
l_SharedVisualModel.BackColor = Color.LightGray;

در نظر داشته باشید وقتی Cell.BackColor را می نویسید، property، به طور اتوماتیک، property of the VisualModel associated را فرا می خواند. جهت تسهیل استفاده از propertyهای رایج تر، اگر بنویسید: Cell.BackColor = Color.Black، سلول به طور اتوماتیک، VisualModel کنونی را clone می کند، backcolor را به رنگ نمونه clone شده تغییر می دهد و نمونه clone شده را به سلول اختصاص می دهد.

DataModel

فضای نامی: SourceGrid2.DataModels

برای نشان دادن valueی یک سلول در یک string format و فراهم کردن یک cell data editor، لازم است property DataModel سلول را populate کنیم. اگر این property، خالی باشد، امکان تغییر valueهای property سلول وجود ندارد و تبدیل رشته (string conversion)، یک ToString ساده value خواهد بود.

یک DataModel معمولاً از یک TypeConverter از نوع داده ی فراخوانده شده جهت مدیریت تبدیل های لازم استفاده می کند، مخصوصاً از تبدیل رشته (که برای نمایش cell value استفاده می شود)

اینها، کلاسهای پیش فرض DataModel در فضای اسمی SourceGrid2.DataModels هستند:

DataModelBase: متد تبدیل را فراهم می کند و اجازه تغییر cell value را فقط توسط کد می دهد، و graphic interface را فراهم نمی کند. این کلاس، پایه همه editorهای دیگری است و همچنین برای مدیریت سلولهای فقط خواندنی بکار می رود، اما با formattingهای customize شده و editorهای مخصوص (مانند CheckBox) سلول از یک editor فقط خواندنی استفاده می کند، زیرا value با کلیک مستقیم روی checkbox تغییر می کند.

EditorControlBase: یک کلاس انتزاعی (Abstract Class) که به استفاده از یک کنترل به عنوان editor سلول کمک می کند.

:EditorTextBox یک TextBox editor. این، کلاسی است که تمامی typeهایی که string conversion را ساپورت می کنند، از آن زیاد استفاده می کنند.

EditorComboBox: یک ComboBox editor

EditorDateTime: یک DateTimePicker editor

EditorNumericUpDown: یک UpDown editor شماره ای

EditorTextBoxButton: امکان edit کردن سلول همه typeهایی را که دارای یک UITypeEditor هستند، فراهم می کند.

یک DataModel را می توان بین سلولهای بیشتری به اشتراک گذاشت، مثلاً می توانید از یک DataModel برای همه سلولهای یک ستون استفاده کرد.

دو راه برای ایجاد یک سلول قابل ویرایش، وجود دارد:

سلول را ایجاد و value type را مشخص کنید.در این حالت، سلول به طور اتوماتیک یک utility function (Utility.CreateDataModel) را فرا می خواند که یک DataModel را در پایه به type مشخص شده باز می گرداند.

grid1[0,0] = new SourceGrid2.Cells.Real.Cell("Hello", 
typeof(string));

DataModel را به صورت جداگانه ایجاد کنید و آن را به سلولها تخصیص دهید.

SourceGrid2.DataModels.EditorTextBox l_TextBox =
new SourceGrid2.DataModels.EditorTextBox(typeof(string));
l_TextBox.MaxLength = 20;
l_TextBox.AttachEditorControl(grid1);
l_TextBox.GetEditorTextBox(grid1).CharacterCasing =
CharacterCasing.Upper;
grid1[2,0].DataModel = l_TextBox;

بعضی از propertyها تا سطح یک DataModel تعریف می شوند، در حالیکه propertyهای دیگر تا سطح یک editor control، در این مورد، property CharacterCasing، تا سطح یک کنترل TextBox تعریف می شود. بنابراین برای استفاده از این propertyها، force کردن یک linking of the editor به grid با متد AttachEditorControl، و سپس فراخوانی متد GetEditorTextBox جهت باز گرداندن نمونه TextBox ، واجب است. این مکانیزم برای ایجاد کردن ویرایشگر مخصوص مانند ComboBox editor نیز مفید است. برای insert کردن یک ComboBox، باید کد زیر را بنویسید:

SourceGrid2.DataModels.EditorComboBox l_ComboBox = 
new SourceGrid2.DataModels.EditorComboBox(
typeof(string),
new string[]{"Hello", "Ciao"},
false);
grid1[3,0].DataModel = l_ComboBox;

البته، ایجاد ویرایشگر DataModel با کنترل سفارشی یا با رفتار مخصوص نیز ممکن است. در تصویر زیر، مشاهده بیشتر ویرایشگرهای دردسترس و بعضی از optionها مانند image properties ممکن است:

clip_image001[7]

BehaviorModel

فضای نامی: SourceGrid2.BehaviorModels

هر سلول دارای یک BehaviorModel است که می توانید آن را با Behaviors property بخوانید. BehaviorModel کلاسی است که رفتار سلول را تعیین می کند. می توان مدلی را را بین سلولهای بیشتری به اشتراک گذاشت و اتعطاف پذیری و سادگی هر ویژگی جدید را امکان پذیر می کند.

اینها، کلاسهای پیش فرض type BehaviorModel هستند:

SourceGrid2.BehaviorModels.Common: رفتار عادی یک سلول

SourceGrid2.BehaviorModels.Header: رفتار یک row header، با ویژگی resize کردن

SourceGrid2.BehaviorModels.ColumnHeader: رفتار یک column header، با ویژگی sort و resize کردن. (به ICellSortableHeader نیاز دارد)

SourceGrid2.BehaviorModels.CheckBox: رفتار یک CheckBox. (به ICellCheckBox نیاز دارد)

SourceGrid2.BehaviorModels.Cursor: اجازه لینک کردن یک cursor را به یک سلول معین می دهد. (به ICellCursor نیاز دارد)

SourceGrid2.BehaviorModels.Button: رفتا ریک Button

SourceGrid2.BehaviorModels.Resize: اجازه resize شدن را با ماوس به سلول می دهد. (مدلهای header، به طور اتوماتیک از این مدل استفاده می کنند)

SourceGrid2.BehaviorModels.ToolTipText: اجازه نمایش یک ToolTipText لینک شده به یک سلول را می دهد. (به ICellToolTipText نیاز دارد)

SourceGrid2.BehaviorModels.Unselectable: نمی گذارد یک سلول، focus را دریافت کند.

SourceGrid2.BehaviorModels.ContextMenu: اجازه نمایش یک context menu لینک شده به یک سلو ل را می دهد. (به ICellContextMenu نیاز دارد)

SourceGrid2.BehaviorModels.CustomEvents: لیستی از رویدادها را که می توان بدون مشتق کردن از یک BehaviorModel، استفاده کرد، expose می کند.

SourceGrid2.BehaviorModels.BindProperty: اجازه لینک کردن valueی یک سلول را به یک property خارجی می دهد.

SourceGrid2.BehaviorModels.BehaviorModelGroup: اجازه ایجاد یک BehaviorModel را می دهد که به طور اتوماتیک لیستی از BehaviorModel را فرا می خواند. زمانی مفید است که یک رفتار، به رفتارهای دیگر نیاز دارد تا درست کار کند.

BehaviorModel که با علامت ستاره مشخص شده است، نیاز به سلولهای مخصوصی دارد تا بتواند وظایفش را اجرا کند، مثلاً، کلاس CheckBox، نیاز به سلولی دارد که interface IcellCheckBox را ساپورت کند.

هر کلاس دارای چند property ثابت است که یک instance پیش فزض را باز می گرداند:

SourceGrid2.BehaviorModels.Common.Default

SourceGrid2.BehaviorModels.Button.Default

SourceGrid2.BehaviorModels.CheckBox.Default

SourceGrid2.BehaviorModels.ColumnHeader.SortableHeader

SourceGrid2.BehaviorModels.ColumnHeader.NotSortableHeader

SourceGrid2.BehaviorModels.Cursor.Default

SourceGrid2.BehaviorModels.Header.Default

SourceGrid2.BehaviorModels.Resize.ResizeHeight

SourceGrid2.BehaviorModels.Resize.ResizeWidth

SourceGrid2.BehaviorModels.Resize.ResizeBoth

SourceGrid2.BehaviorModels.RowHeader.Default

SourceGrid2.BehaviorModels.ToolTipText.Default

SourceGrid2.BehaviorModels.Unselectable.Default

در کد زیر، من یک BehaviorModel ایجاد کرده ام که backcolor سلول را هنگامی که کاربر ماوس را روی آن قرار میدهد، تغییر می دهد:

public class CustomBehavior : SourceGrid2.BehaviorModels.BehaviorModelGroup
{
public override void OnMouseEnter(SourceGrid2.PositionEventArgs e)
{
base.OnMouseEnter (e);
((SourceGrid2.Cells.Real.Cell)e.Cell).BackColor = Color.LightGreen;
}
public override void OnMouseLeave(SourceGrid2.PositionEventArgs e)
{
base.OnMouseLeave (e);
((SourceGrid2.Cells.Real.Cell)e.Cell).BackColor = Color.White;
}
}

برای استفاده از این BehaviorModel، این کد را در رویداد Load یک فرم، insert کنید:

grid1.Redim(2,2);

CustomBehavior l_Behavior = new CustomBehavior();
for (int r = 0; r < grid1.RowsCount; r++)
for (int c = 0; c < grid1.ColumnsCount; c++)
{
grid1[r,c] = new SourceGrid2.Cells.Real.Cell("Hello");
grid1[r,c].Behaviors.Add(l_Behavior);
}

سلولها

فضای نامی: SourceGrid2.Cells

اینها، سلولهای پیش فرض در دسترس هستند:

SourceGrid2.Cells.Virtual: این فضای نامی، حاوی تمامی سلولهای مجازی است که می توان با یک کنترل GridVirtual استفاده کرد، همه اینها، سلولهای انتزاعی (abstract) هستند و باید از این سلولها مشتق شوند تا بتوانید از منبع داده سفارشی تان استفاده کنید.

CellVirtual: سلول پایه همه پیاده سازی های دیگر (implementation)، برای رایج ترین نوع سلولهای مجازی استفاده میز شود.

Header: یک سلول header.

ColumnHeader: یک سلول column header.

RowHeader: یک سلول row header.

Button: یک سلول button

CheckBox: یک سلول checkbox

ComboBox: یک سلول combobox

Link: یک سلول link style

SourceGrid2.Cells.Real: این فضای نامی حاوی تمامی سلولهای واقعی است می توان با یک کنترل Grid استفاده کرد.

Header: یک سلول header.

ColumnHeader: یک سلول column header.

RowHeader: یک سلول row header.

Button: یک سلول button

CheckBox: یک سلول checkbox

ComboBox: یک سلول combobox

Link: یک سلول link style

هدف این کلاسها، ساده کردن استفاده از VisualModel، DataModel، و BehaviorModel است. اگر ما نگاهی به کد هر کدام از این کلاسها بیاندازیم، می ببنینم که این کلاسها از مدلهای قبلی استفاده می کنند. اما مدلهایی وجود دارند که به interface های مخصوصی نیاز دارند و در این مورد، همه interface های لازم را انجام می دهد. مثلاً کد زیر، کد سلول SourceGrid2.Cells.Real.CheckBox است:

public class CheckBox : Cell, ICellCheckBox
{
public CheckBox(string p_Caption, bool p_InitialValue)
{
m_Caption = p_Caption;

DataModel = new SourceGrid2.DataModels.DataModelBase(typeof(bool));
VisualModel = SourceGrid2.VisualModels.CheckBox.MiddleLeftAlign;
Behaviors.Add(BehaviorModels.CheckBox.Default);

Value = p_InitialValue;
}
public bool Checked
{
get{return GetCheckedValue(Range.Start);}
set{SetCheckedValue(Range.Start, value);}
}
private string m_Caption;
public string Caption
{
get{return m_Caption;}
set{m_Caption = value;}
}
public virtual bool GetCheckedValue(Position p_Position)
{
return (bool)GetValue(p_Position);
}
public virtual void SetCheckedValue(
Position p_Position, bool p_bChecked)
{
if (DataModel!=null && DataModel.EnableEdit)
DataModel.SetCellValue(this, p_Position, p_bChecked);
}
public virtual CheckBoxStatus GetCheckBoxStatus(Position p_Position)
{
return new CheckBoxStatus(DataModel.EnableEdit,
GetCheckedValue(p_Position), m_Caption);
}
}

همانطور که می بینید، کلاس CheckBox، فقط از مدلهای SourceGrid2.DataModels.DataModelBase(typeof(bool))، استفاده می کند. SourceGrid2.VisualModels.CheckBox.MiddleLeftAlign e BehaviorModels.CheckBox.Default، رابط ICellCheckBoxرا با متد GetCheckBoxStatus اجرا می کند. متدهای Checked، Caption، GetCheckedValue، و SetCheckedValue، متدهایی هستند که ویرایش valueی سلول را ساده می کنند.

ساختار Grid

ردیفها و ستونها (Rows and Columns)

اجزای اصلی یک grid، ردیفها و ستونها هستند. جهت تغییر دادن این اطلاعات، SourceGrid، دو property فراهم می کند:

Rows: مجموعه ای از type RowInfoCollection را بازمی گرداند که یک strip از کلاسهای RowInfo است.

Columns: مجموعه ای از type ColumnInfoCollection را بازمی گرداند که لیستی از کلاسهای ColumnInfo است.

اینها، بعضی از propertyهای کلاس RowInfo هستند: Height ، Top، Bottom،

اینها هم، propertyهای کلاس ColumnInfo هستند: Width، Left، Right، Index، Tag.

راههای زیادی جهت تغییر دادن (manipulate) ردیفها و ستونها وجود دارد:

grid1.Redim(2,2);
grid1.RowsCount = 2;
grid1.ColumnsCount = 2;

 

grid1.Rows.Insert(0);
grid1.Rows.Insert(1);
grid1.Columns.Insert(0);
grid1.Columns.Insert(1);

این سه مثال، تمامی کارهای ایجاد یک جدول با 2 ردیف و 2 ستون را انجام می دهد.

جهت تغییر پهنا یا ارتفاع یک ردیف یا ستون، می توان از این کد استفاده کرد:

grid1.Rows[0].Height = 100;
grid1.Columns[0].Width = 100;

 

propertyهای Top، Bottom، Left و Right، با استفاده از پهنا و ارتفاع ردیفها و ستونها به طور اتوماتیک محاسبه می شوند.

Panelها
برای مدیریت صحیح scrollbarها، ستونها، ردیفهای ثابت، و جزییات دیگر، ساختار panelهای grid داخلی باید مانند شکل زیر باشد:

1.    TopLeftPanel : سلولهای ردیف و ستون ثابت را نگه می دارد.
2.    TopPanel : ردیفهای ثابت را نگه می دارد.
3.    LeftPanel : ستونهای را ثابت نگه می دارد.
4.    ScrollablePanel : سلولهای غیر ثابت را ثابت نگه می دارد.
5.    HScrollBar : ScrollBar افقی
6.    VScrollBar : ScrollBar عمودی
7.    BottomRightPanel : پنل مدیریت فضای کم بین دو scrollbar

رویدادها
رویدادهای ماوس و کیبورد را می توان با یک BehaviorModel استفاده کرد یا می توان مستقیماً به grid وصل کرد. همه رویدادها ابتدا به panelها و سپس به طور اتوماتیک به کنترلهای GridVirtual و Grid،اجرا می شوند. جهت استفاده از این رویدادها می توانید کد زیر را بنویسید:

grid.MouseDown += new System.Windows.Forms.MouseEventHandler(
grid_MouseDown);

می توان این کار را با Visual Studio designer نیز انجام داد.

ContextMenu

Grid، دارای یک ContextMenu پیش فرض است که می توان آنرا با ContextMenuStyle property، سفارشی کرد. می توان یک ContextMenu را به شی Selection با Grid.Selection و ContextMenuItemsمتصل کرد، که برای تمامی سلولهای انتخاب شده قابل استفاده است؛ در غیر این صورت، می توانید یک ContextMenu را مستقیماً به یک سلول معین متصل کرد.

اطلاعات دیگر

Focus و Selection

یک سلول می تواند یا انتخاب شود و یا focus داشته باشد. فقط یک سلول می تواند focus را داشته باشد، که FocusCellPosition property of the grid آن را شناسایی می کند، در عوض، سلولهای زیادی می توانند انتخاب شوند. یک سلول وقتی انتخاب می شود که در Selection object of the grid حاضر باشد. سلول دارای focus، تمامی رویدادهای ماوس و کیبورد را دریافت می کند، در حالیکه سلولهای انتخاب شده اعمالی از قبیل copy و paste را دریافت می کنند.

Position و Range

دو تا از پرکاربردترین اشیاء در پروژه SourceGrid، Position و Range هستند. Position، موقعیتی را با یک ردیف و ستون مشخص می کند، درحالیکه Range، گروهی از سلولهای نامحدود را از یک start Position و یک end Position، شناسایی می کند.

Performance

برای بهینه کردن اجرای این کنترل، از کنترل GridVirtual، هنگامی که نمایش سلولهای زیادی واجب است، استفاده کنیدو همیشه سعی کنید مدلهای DataModel، VisualModel، و BehaviorModel را بین سلولهای بیشتری به اشتراک بگذارید. اجرای (performance)grid ، حتی اگر ترسیم (drawing) کد هنوز قابل بهینه سازی باشد، تقریباً خوب است، مخصوصاً هنگام scroll کردن.

Extensionها

در پروژه SampleProject، مثالها و بخشهای زیادی از کد وجود دارند که می توانند ایده ها و پیشنهادهایی درباره چگونگی پیاده سازی custom grid، ارایه می کنند، بویژه در پوشه Extensionها، gridهایی وجود دارند عملکردهایی مثل bind کردن به یک DataSet (DataTable)، به یک Array، و به یک ArrayList را فراهم می کنند.

Screenshotها

clip_image001[9]

clip_image002[6]

clip_image003[6]

چگونگی انتخاب کل یک ردیف:

grid1.Rows[1].Select = true;

چگونگی انتخاب همه سلولها:

grid1.Selection.AddRange(grid1.CompleteRange);

چگونگی ایجاد یک editor با قانون اعتبارسنجی پیشرفته:

grid1[0,0] = new SourceGrid2.Cells.Real.Cell(2, typeof(int));
grid1[0,0].DataModel.MinimumValue = 2;
grid1[0,0].DataModel.MaximumValue = 8;
grid1[0,0].DataModel.DefaultValue = null;
grid1[0,0].DataModel.AllowNull = true;

چگونگی ایجاد یک ویرایشگر ComboBox برای نمایش یک valueی متفاوت از valueی واقعی استفاده شده.

در این مورد، زمانیکه valueی واقعی یک double است، به صورت یک string نمایش داده می شود.

double[] l_RealValues = new double[]{0.0,0.5,1.0};
SourceGrid2.DataModels.EditorComboBox l_EditorCombo =
new SourceGrid2.DataModels.EditorComboBox(typeof(double));
l_EditorCombo.StandardValues = l_RealValues;
l_EditorCombo.StandardValuesExclusive = true;
l_EditorCombo.AllowStringConversion = false;
SourceLibrary.ComponentModel.Validator.ValueMapping l_Mapping =
new SourceLibrary.ComponentModel.Validator.ValueMapping();
l_Mapping.ValueList = l_RealValues;
l_Mapping.DisplayStringList = new string[]{"Zero", "One Half", "One"};
l_Mapping.BindValidator(l_EditorCombo);
grid1[0,0] = new SourceGrid2.Cells.Real.Cell(0.5, l_EditorCombo);

ویژگی ها

کارهایی که SourceGrid می تواند امجام دهد:

سفارشی کر دن ظاهر گرافیکی، نوع ویرایشگر و رفتار (cursor، tooltiptext، contextmenu) هر سلول.

همه انواع داده هایی را که TypeConvertor یا UITypeEditor دارند، ساپورت می کند.

هر کنترل .NET را می توان مثل editor با خطوط کم کد استفاده کرد.

می توانید ردیف ها و ستون ها را اضافه، حذف و جابجا کنید.

می توان ارتفاع و پهنای هر ستون و ردیف را به طور مستقل سفارشی کرد، و یا می توان به طور اتوماتیک و بر اساس محتویات سلول محاسبه کرد.

ویژگی های RowSpan و ColumnSpan را جهت یکی کردن سلولهای بیشتری ساپورت می کند.

عملیات اتوماتیک Copy و Paste را ساپورت می کند.

column sort را ساپورت می کند.

می توانید پهنا و ارتفاع ستونها و ردیفها را تغییر دهید.

در همه سلولها، سفارشی کردن تصویر و alignment متن و تصویر امکان پذیر است.

متن MultiLine و WordWrap را ساپورت می کند.

خروج (export) HTML را ساپورت می کند.

با بعضی از extensionها، ویژگی های data binding را ساپورت می کند.

سلولهای مجازی که برای binding هر نوع منبع داده استفاده می شود را ساپورت می کند.

و کارهایی که نمی تواند انجام دهد:

SourceGrid، دارای designer نیست، همه را باید با کد انجام داد.

چاپ کردن را هم ساپورت نمی کند.

تغییر دادن کد SourceGrid

تغییر دادن، compile مجدد، و توزیع کنترل SourceGrid، برای استفاده شخصی و تجاری مجاز است.

Developmentهای آینده

بهبود ترسیم کد (drawing code)

ساپورت Masked Edit textbox

مشکلات شناخته شده

ساپورت Cut وجود ندارد

ویرایشگر NumericUpDown، به طور صحیح به سلول align نمی شود.

کلید shift با arrow keys کار نمی کند و سلولهای header هنوز مشکل دارند.

نسخه های قبلی

نسخه 2 SourceGrid، دارای تغییرات زیادی بود، و لیست کردن همه چیز ممکن نبود. حالت استفاده خیلی شیبه است، اما تبدیل یک کد نوشته شده با نسخه های قبلی ساده نیست. چند پیشنهاد وجود دارد:

ویژگی اصلی grid این است که با ICellVirtual interface کار می کند، نه با کلاس Cell. این Interface، فقط حاوی متدهای لازم است و بنابراین ضعیفتر است.

کدی که قبلاً برای این وجود داشت:

grid[0,0] = new SourceGrid.Cell("Ciao");
grid[0,0].BackColor = Color.White;

و حالا باید این گونه باشد:

SourceGrid2.Cells.Real.Cell l_Cell = 
new SourceGrid2.Cells.Real.Cell("Ciao");
l_Cell.BackColor = Color.White;
grid[0,0] = l_Cell;

در نسخه قبلی، سلول پایه از Cell متمایز شد، در حالیکه interface IcellVirtual وجود دارد و تغییر مهم این کلاس این است که اطلاعات در مورد موقعیت ردیف و ستون را در بر نمی گیرد.

حالا Grid به طور ذاتی property BorderStyle را که قادر به حذف Panel نهایی است، و قبلاً جهت ایجاد یک border لازم بود، ساپورت می کند.

حالا همه کدهایی که ابتدا به رویدادهای یک سلول bind شدند، باید به یک BehaviorModel منتقل شوند، مثلاً می توانید از SourceGrid2.BehaviorModels.CustomEvents استفاده کنید.

شی Selection، دیگر مجموعه ای از سلولها محسوب نمی شود، بلکه مجموه ای از range است.

با insert کردن اشیاء ردیف و ستون، کدی که ابتدا باید روی خطوط و ستونها کار کند، نتیجه ساده تری دارد، به علاوه،متدهای زیاد دیگری که قبلاً درGrid بودند، حالا در کلاسهای ColumnInfoCollection یا ColumnInfo هستند.

شی CellsContainer، دیگر وجود ندارد، و حتی اگر از panelها جایگزین شود، commonهای بیشتری به مستقبماً به grid لینک می شوند، و بنابراین کدی که قبلاً از CellsContainer استفاده می کرد، حالا میط تواند مستقیماً از کنترل grid استفاده کند.

شی قدیمی ICellModel، حالا شی IDataModel است، در حالیکه شی VisualProperties الان IVisualModel شده است.

کلاس CellControl، فعلاً دیگر ساپورت نمی شود.

برای دانلود مقالات بیشتر به سایت آموزشگاه تحلیلگر داده ها

http://WWW.Tahlildadeh.com مراجعه فرمایید.