PDA

View Full Version : تناظر بین checked list box و دیتاگرید ویو



mhdhp86
شنبه 04 آذر 1391, 17:08 عصر
با سلام خدمت دوستان
من در مورد این سئوالی که دارم تو سایت سرچ کردم اما چیزی دست گیرم نشد در واقع نمی دونستم چی باید سرچ کنم که جواب سئوالم رو پیدا کنم!

من یک دیتا گرید دارم که حدود 30 ستون داره. اما همیشه به همه آنها احتیاج ندارم. در نتیجه تصمیم گرفتم یک checklistbox بگذارم و اسم ستون ها رو بنویسم تا موقع اجرا هر ستونی که لازمه کنار اسمش تیک بخوره و بقیه ستون ها invisible بشن.
حالا سئوالم اینه که آیا راهی هست که هر گزینه از چک لیست متناظر با یک ستون بشه و من کمتر کد بزنم؟ یعنی مجبور نشم برای 30 ستون 30 تا دستور if بذارم.
البته فکر می کنم بتونم با یک حلقه for و با اندیس این کار رو بکنم ولی ترجیحا می خوام ستون ها رو با اسمشون استفاده کنم نه با اندیسشون.
آیا به جز استفاده از چک لیست باکس روش دیگه ای برای این کار وجود داره؟

plus
شنبه 04 آذر 1391, 17:34 عصر
سلام. این کد هیچ وابستگی به نوع یا تعداد ستون ها نداره.اسمشون هم مهم نیست چی باشه.عنوان ستون توی چک لیست نمایش داده میشه:


class CheckedColumnItem
{
DataGridViewColumn column;

public CheckedColumnItem(DataGridViewColumn Column)
{
column = Column;
}

public DataGridViewColumn Column
{
get { return column; }
}
public override string ToString()
{
return column.HeaderText;
}
}
public Form1()
{
InitializeComponent();
checkedListBox1.Items.Clear();
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
CheckedColumnItem cci = new CheckedColumnItem(column);
checkedListBox1.Items.Add(cci);
checkedListBox1.SetItemChecked(checkedListBox1.Ite ms.IndexOf(cci), column.Visible);
}

}
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
((CheckedColumnItem)checkedListBox1.Items[e.Index]).Column.Visible = (e.NewValue == CheckState.Checked);
}

mhdhp86
شنبه 04 آذر 1391, 17:43 عصر
خیلی ممنون از کدتون. میشه یک مقدار توضیح بدید؟ این طور که من متوجه شدم این با اندیس کار می کنه. اینجا اول دیتا گرید ویو اطلاعات رو آورده بعد با تیک زدن یک ستون هایی اضافه میشه بهش؟
چون می می خوام اول کاربرم گزینه هایی که می خواد رو انتخاب کنه بعد با فشردن دکمه اطلاعات بیان تو دیتاگرید.

plus
شنبه 04 آذر 1391, 17:54 عصر
این کد توی لود فرم به ازای هر ستون گرید، یک آیتم به چک لیست اضافه میکنه و در صورتی که در اون لحظه اون ستون Visible باشه اون آیتم چک هم میخوره...
هر آیتمی که توی چک لیست اضافه میشه ستون گرید رو هم در خودش نگه می داره تا وقتی کاربر اون آیتم رو انتخاب کنه یا از انتخاب خارج کنه، توی رویداد checkedListBox1_ItemCheck وضعیت Visible اون ستون رو بلافاصله عوض میکنه.
شما کد رو اجرا کنی بهتر متوجه میشی چطوری عمل میکنه.
ولی اگه میخوای تغییر نمایش آیتم ها به لحظه نباشه، کد مربوط به رویداد رو بردار و جاش میتونی چیزی مثل این بگذاری:


private void button1_Click(object sender, EventArgs e)
{
foreach (object item in checkedListBox1.Items)
((CheckedColumnItem)item).Column.Visible = GetItemChecked(checkedListBox1.Items.IndexOf(item) );
}

این قسمت کد، با کلیک بر روی دکمه، وضعیت نمایش ستون رو بر اساس وضعیت انتخاب هر آیتم تعیین میکنه.
اگر هم میخوای اول کار هیچ ستونی نمایش داده نشه میتونی از Design مشخصه Visible همه اونا رو False کنی.
در ضمن این کد هیچ ستونی به گرید اضافه نمیکنه، فقط Visible اون ها رو عوض میکنه. فرض شده که ستون ها در InitializeComponent به گرید اضافه شدن.

mhdhp86
شنبه 04 آذر 1391, 18:01 عصر
بله این همون چیزی هست که می خوام. همه فیلد ها به طور پیش فرض invisible هستند. خیلی متشکر
پس نمیشه این کار رو با نام ستون انجام داد و حتما باید از ایندکس استفاده کرد.

plus
شنبه 04 آذر 1391, 18:07 عصر
دقیقا متوجه منظورت نمیشم.کارای مختلفی میشه کرد ولی این روش به نام ستون یا ترتیب یا اندیس ستون ها هم غیر وابستس.اگه قرار باشه از نام ستون استفاده بشه شما باید اگه 30 تا ستون داری اسم 30 تا ستون رو بیاری...
از ایندکس هم به طور مستقیم و وابسته استفاده نشده. یعنی ما اصلا کاری به ایندکس ستون های گرید نداریم. فقط از IndexOf چک لیست استفاده شده چون بدون داشتن Index یک آیتم کلا نمیتونین وضعیت Check شده یا نشده آیتم چک لیست رو بفهمید.

mhdhp86
یک شنبه 05 آذر 1391, 14:13 عصر
در واقع الان باید ایتم های چک لیستم به همان ترتیبی باشند که ستون هام هستند.یعنی ایندکسشون یکی باشه

plus
یک شنبه 05 آذر 1391, 15:53 عصر
نه هر آیتم خودش ستون مربوط به خودش رو نگه میداره مهم نیست ترتیبشون ولی چون آیتم ها بوسیله کد (توی لود فرم) و به ازای هر ستون توی حلقه foreach تولید میشن، خود به خود ترتیبشون با ستون ها یکی میشه.ولی اکه ترتیبشون عوض بشه مشکلی ایجاد نمیکنه.

mhdhp86
شنبه 11 آذر 1391, 17:52 عصر
نه هر آیتم خودش ستون مربوط به خودش رو نگه میداره مهم نیست ترتیبشون ولی چون آیتم ها بوسیله کد (توی لود فرم) و به ازای هر ستون توی حلقه foreach تولید میشن، خود به خود ترتیبشون با ستون ها یکی میشه.ولی اکه ترتیبشون عوض بشه مشکلی ایجاد نمیکنه.
متوجه نمیشم.چه طور می فهمه کدوم ایتم مربوط به کدوم ستونه؟
الان همه ستون ها هستند ولی visible انها false هست. حالا قراره هر گزینه ای که تو چک باکس تیک می خوره ستونش visible بشه

mhdhp86
شنبه 11 آذر 1391, 18:10 عصر
من می خوام بدونم همچین کدی ممکنه؟


foreach (object item in checkedListBox1.Items)
if (checkedListBox1 .ItemCheck ==true )
dataGridView1.Columns[item ].Visible=true ;

این کد غلطه . درستش رو نمی دونم چه طور باید بنویسم

plus
شنبه 11 آذر 1391, 19:25 عصر
متوجه نمیشم.چه طور می فهمه کدوم ایتم مربوط به کدوم ستونه؟
الان همه ستون ها هستند ولی visible انها false هست. حالا قراره هر گزینه ای که تو چک باکس تیک می خوره ستونش visible بشه
توی کدی که دادم:


class CheckedColumnItem
{
DataGridViewColumn column;

public CheckedColumnItem(DataGridViewColumn Column)
{
column = Column;
}

public DataGridViewColumn Column
{
get { return column; }
}
public override string ToString()
{
return column.HeaderText;
}
}
public Form1()
{
InitializeComponent();
checkedListBox1.Items.Clear();
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
CheckedColumnItem cci = new CheckedColumnItem(column);
checkedListBox1.Items.Add(cci);
checkedListBox1.SetItemChecked(checkedListBox1.Ite ms.IndexOf(cci), column.Visible);
}

}

در لود فرم، به ازای هر ستون از گرید:
A. یک شی از نوع CheckedColumnItem ساخته میشه و به سازنده این کلاس، خود ستون داده میشه تا هر شی، ستون مربوط به خودش رو نگه داره.
B. شی ساخته شده به عنوان آیتم به CheckedListBox اضافه میشه.
C. اگه ستون، Visible بود، آیتم اضافه شده چک میخوره.

حالا، حالتی که کد تغییر Visible رو در دکمه گذشتم:


private void button1_Click(object sender, EventArgs e)
{
foreach (object item in checkedListBox1.Items)
((CheckedColumnItem)item).Column.Visible = GetItemChecked(checkedListBox1.Items.IndexOf(item) );
}

به ازای هر آیتم در CheckedListBox:
A. از اونجا که این آیتم ها از نوع کلاس CheckedColumnItem هستن، ابتدا آیتم Cast میشه به نوع CheckedColumnItem.
B. همونطور که گفتم هر شی از این نوع، یک Reference به یک ستون گرید رو نگه میداره. پس اینجا ستون مربوط به اون آیتم رو داریم.
C.وضعیت چک شده یا نشده آیتم، با استفاده از متد GetItemChecked در میاد. این متد اندیس رو میگیره. برای بدست آورد اندیس آیتمی که داریم روش کار میکنیم، از Items.IndexOf استفاده میکنیم.
D.مشخصه Visible ستون مربوطه، بر اساس وضعیت چک بودن یا نبودن آیتم تنظیم میشه.
این روش استاندارد برای کاری هست که میخواهین بکنین.

plus
شنبه 11 آذر 1391, 19:44 عصر
من می خوام بدونم همچین کدی ممکنه؟


foreach (object item in checkedListBox1.Items)
if (checkedListBox1 .ItemCheck ==true )
dataGridView1.Columns[item ].Visible=true ;

این کد غلطه . درستش رو نمی دونم چه طور باید بنویسم

ItemCheck یک رویداد هست نه مشخصه یا متدی که تعیین کنه که یک آیتم چک شده یا نه، باید از


checkedListBox1.GetItemChecked(checkedListBox1.Ite ms.IndexOf(item));

و در مورد خط بعد:


dataGridView1.Columns[item ].Visible=true ;

شما در صورتی میتونی اینکار و بکنی که هر آیتم، خود ستون، اندیس ستون یا نام ستون باشه (البته از اونجایی که آیتم به صورت کلی object هست قبلش باید cast بشه) تا بتوی بدیش به dataGridView1.Columns.
در مثالی که من نوشتم، این طور نبود، هر آیتم ما یک شی از کلاس CheckedColumnItem بود که ستون رو در خودش نگه میداشت.اگه از همین کلاس بخوای استفاده کنی میتونی اینطوری بنویسی:



private void button1_Click(object sender, EventArgs e)
{
foreach (object item in checkedListBox1.Items)
{
CheckedColumnItem ccItem = (CheckedColumnItem )item; // Type cast
if ( checkedListBox1.GetItemChecked(checkedListBox1.Ite ms.IndexOf(item) )
dataGridView1.Columns[ccItem.Column.Name].Visible=true ;
else
dataGridView1.Columns[ccItem.Column.Name].Visible=false;
}
}

در کل من نمیفهمم شما دنبال چی هستی.

mhdhp86
شنبه 11 آذر 1391, 19:52 عصر
:لبخند: واقعا؟ خیلی پیچیده گفتم؟!!
من میرم این کد ها رو میزنم اگر مشکلی بود مزاحم میشم!

mhdhp86
شنبه 11 آذر 1391, 20:09 عصر
راستی اینو یادم رفت بگم که این GetItemChecked رو نمیشناسه. باید چه کلاسی رو اضافه کنم به فرمم؟





private void button1_Click(object sender, EventArgs e)
{
foreach (object item in checkedListBox1.Items)
((CheckedColumnItem)item).Column.Visible = GetItemChecked(checkedListBox1.Items.IndexOf(item) );
}

ا.

plus
شنبه 11 آذر 1391, 20:15 عصر
راستی اینو یادم رفت بگم که این GetItemChecked رو نمیشناسه. باید چه کلاسی رو اضافه کنم به فرمم؟

منظور، checkedListBox1.GetItemChecked بود.اصلاح میکنم.

mhdhp86
شنبه 11 آذر 1391, 21:49 عصر
خیلیییی ممنون..... عالیه.درست شد