ورود

View Full Version : ايجاد ستوني از UserControl در DataGridView



رافعی مهدی
شنبه 19 مرداد 1387, 06:24 صبح
(اميدوارم سوالم زياد تكراري نباشه)

با سلام
آيا امكان داره (ترجيحاً بدون استفاده از WPF) ستوني از UserControl در DataGridView ايجاد كرد؟




.

a_mzadeh
شنبه 19 مرداد 1387, 16:09 عصر
سلام، اگر منظور شما از يوزر كنترل، كنترلهاي ساده اي مثل تكس باكس، لنيك ليبل، باتن، كمبو باكس هست، بايد عرض كنم در قسمت column type از ستونهاي ديتا گريد ويو، مي توني استفاده كني.

رافعی مهدی
شنبه 19 مرداد 1387, 18:29 عصر
عرض شود كه نه!
UserControl آيتمي است كه برنامه نويس براي خودش به دلخواه طراحي مي كند. براي اضافه كردن آن به يك Solution به قسمت ...Add New Item مراجعه كنيد.

mamadgmail
شنبه 19 مرداد 1387, 23:07 عصر
بله در msdn مثالی برای این کار وجود دارد

رافعی مهدی
یک شنبه 20 مرداد 1387, 07:24 صبح
بله در msdn مثالی برای این کار وجود دارد
راستش بهترين كدي كه در msdn پيدا كرده بودم مثالي بود كه در آن يك CellType جديد ساخته مي شد و سپس بر اساس اين الگو (Template) يك ستون جديد. منتهي در اين مثال خصوصيتي كه اين ستون جديد پيدا مي كنه تنها اين است كه يك Internal Border به هر Cell اضافه مي شه. حالا هم دارم سعي مي كنم يه جوري اين مثال رو به كار خودم ربط بدم. URL اين مثال در msdn اينه:


::2005
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_fxmclictl/html/9b7dc7b6-5ce6-4566-9949-902f74f17a81.htm

::2008
ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_fxmclictl/html/9b7dc7b6-5ce6-4566-9949-902f74f17a81.htm


ولي مثال مستقيم و سر راستي راجع به اينكه چطور ميشه ستوني از UserControl ساخت، پيدا نكردم.
ممكنه شما URL مثالي كه گفتيد در msdn وجود داره رو بفرماييد؟





.

رافعی مهدی
سه شنبه 22 مرداد 1387, 00:07 صبح
آنچه كه تا اينجا متوجه شدم اينه كه دو راه حل كلي براي اين كار وجود دارد:
1- سلول و سپس ستوني با جنس جديد كه از يكي از انواع استاندارد DataGridViewCell مثل TextBox يا Image يا ... ارث بري مي كند تعريف كرده، خصوصيات دلخواه را به آن اضافه كنيم
(مثلاً نمونه پروژه ي پيوست شده)

2- كنترل دلخواهي از جمله يك UserControl را به مجموعه كنترلهاي DataGridView اضافه نمائيم و رفتارها و خصوصيات آن را كنترل كنيم.
مثلاً كد زير:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Sample5
{
public partial class DgvTextAndButton : Form
{
public DgvTextAndButton()
{
InitializeComponent();
}

private void DgvTextAndButton_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("col1");
dt.Columns.Add("col2");
for (int j = 0; j < 20; j++)
{
dt.Rows.Add("col1"+j.ToString(),"col2"+j.ToString());
}
this.dataGridView1.DataSource = dt;
this.dataGridView1.Columns[0].Width = 150;

this.txbtnControl = new TextAndButtonControl();
this.txbtnControl.Visible = false;
this.dataGridView1.Controls.Add(this.txbtnControl) ;

//Handle this event to paint a textbox and button style in the cell,
//this painting avoid using amount of usercontrols, we just need one
this.dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1 _CellPainting);

//Handle the cellbeginEdit event to show the usercontrol in the cell while editing
this.dataGridView1.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView1_C ellBeginEdit);
//Handle the cellEndEdit event to update the cell value
this.dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEnd Edit);

//Handle the scroll event to reset the location and size of the usercontrol while scrolling
this.dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);
}

TextAndButtonControl txbtnControl;

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView1.NewRowIndex)
{
Rectangle textRect = e.CellBounds;
textRect.Width -= e.CellBounds.Width / 3;
Rectangle btnRect = e.CellBounds;
btnRect.X += textRect.Width;
btnRect.Width = e.CellBounds.Width / 3;
e.Paint(textRect, DataGridViewPaintParts.All);
ControlPaint.DrawButton(e.Graphics, btnRect, ButtonState.Normal);
StringFormat formater = new StringFormat();
formater.Alignment = StringAlignment.Center;
e.Graphics.DrawString("click", e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), btnRect, formater);
e.Handled = true;
}
}

void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView1.NewRowIndex)
{
Rectangle rect = this.dataGridView1.GetCellDisplayRectangle(e.Colum nIndex, e.RowIndex, true);
this.txbtnControl.Location = rect.Location;
this.txbtnControl.Size = rect.Size;
this.txbtnControl.Text = this.dataGridView1.CurrentCell.Value.ToString();
this.txbtnControl.ButtonText = "click";
this.txbtnControl.renderControl();
this.txbtnControl.Visible = true;
}
}

void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView1.NewRowIndex)
{
this.dataGridView1.CurrentCell.Value = this.txbtnControl.Text;
this.txbtnControl.Visible = false;
}
}

void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
if (this.txbtnControl.Visible == true)
{
Rectangle r = this.dataGridView1.GetCellDisplayRectangle(
this.dataGridView1.CurrentCell.ColumnIndex,
this.dataGridView1.CurrentCell.RowIndex,
true);
this.txbtnControl.Location = r.Location;
this.txbtnControl.Size = r.Size;
}
}
}

class TextAndButtonControl : UserControl
{
private TextBox textbox1;
private Button button1;

public TextAndButtonControl()
{
this.textbox1 = new TextBox();
this.Controls.Add(this.textbox1);

this.button1 = new Button();
this.Controls.Add(this.button1);

this.renderControl();
this.button1.Click += new EventHandler(button1_Click);
}

void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Click! The value is:" + this.Text);
}

public string Text
{
get { return this.textbox1.Text; }
set { this.textbox1.Text = value; }
}

public string ButtonText
{
get { return this.button1.Text; }
set { this.button1.Text = value; }
}

public void renderControl()
{
this.textbox1.Location = new Point(0, 0);
this.textbox1.Width = 2 * this.Width / 3;
this.textbox1.Height = this.Height;

this.button1.Location = new Point(2 * this.Width / 3, 0);
this.button1.Width = this.Width / 3;
this.button1.Height = this.Height;
}
}
}

منبع:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1425662&SiteID=1

كه در آن يك دكمه و يك تكست باكس در غالب يك UserControl در يك سلول نمايش داده مي شود.

اما در هر دوي اين روشها يك مشكل اصلي وجود دارد و آن اين است كه اگر بخواهيم يك UserControl كه در آن هيچ كامپوننت معمولي مثل دكمه و ... وجود ندارد را در يك Cell نمايش دهيم راه حلي ارائه نشده است. به عبارت ديگر مشكل اصلي نحوه ي نمايش UserControl در DataGridViewCell است.



.

ASKaffash
سه شنبه 22 مرداد 1387, 08:03 صبح
سلام
حناب رافعی آیا شما دقیقا میخواهید در DataGridView یک ستون سفارشی داشته باشید ؟
خوب قطعا میدانید که ستونهای هر DGV محدود است وبهترین کار همان است که شما در سورس نمونه انجام دادید یعنی اینکه رویداد CellPainting را مدیریت میکنید ولی خوب است که شما یک کنترل سفارشی ایجاد کنید که خودش از کلاس DGV به ارث میبرد بعد خاصیت مثلا Tag آن ستون مورد نظر را بک مقدار دلخواه Set کنید در هنگام ترسیم توسط رویداد CellPainting ستون اگر با Tag مورد نظر معادل باشد عملیات گرافیکی مشابه UserControl مورد سئوال را درآن پیاده سازی کنید. امیدوارم منظور را درست منتقل کرده باشم

رافعی مهدی
سه شنبه 22 مرداد 1387, 08:56 صبح
سلام
حناب رافعی آیا شما دقیقا میخواهید در DataGridView یک ستون سفارشی داشته باشید ؟
خوب قطعا میدانید که ستونهای هر DGV محدود است وبهترین کار همان است که شما در سورس نمونه انجام دادید یعنی اینکه رویداد CellPainting را مدیریت میکنید ولی خوب است که شما یک کنترل سفارشی ایجاد کنید که خودش از کلاس DGV به ارث میبرد بعد خاصیت مثلا Tag آن ستون مورد نظر را بک مقدار دلخواه Set کنید در هنگام ترسیم توسط رویداد CellPainting ستون اگر با Tag مورد نظر معادل باشد عملیات گرافیکی مشابه UserControl مورد سئوال را درآن پیاده سازی کنید. امیدوارم منظور را درست منتقل کرده باشم
سلام آقاي كفاش
بله دقيقاً مي خواهم همين كار را انجام دهم. بهتر است واضح تر بگويم.
قطعاً در WindowsMediaPlayer و در Library آن ديده ايد كه ستوني وجود دارد كه در آن چند ستاره قرار دارد و براي كلاسه بندي آيتم ها استفاده مي شود. مي خواهم در برنامه ام ستوني مشابه اين داشته باشم. براي اين كار كامپوننت (UserControl) پنج ستاره را طراحي كردم، ولي از آنجا كه اگر هر يك از ستاره ها را يك Button در نظر بگيرم Border آن به زيبايي كار لطمه مي زند، كامپوننت ستاره را نيز طراحي كردم و با استفاده از دستور Region آن را به شكل ستاره در آورده ام. بنابراين كامپوننت اصلي ام شامل پنج نمونه از كامپوننت ستاره است.
حالا از هر يك از دو روش بالا كه بخواهيم اين ستون را ايجاد كنيم، بحث مربوط به ترسيمات گرافيكي با سؤال مواجه ميشود.
اگر ممكن است با توجه به اين توضيحات بفرماييد كه ايده ي شما چيست؟

ASKaffash
سه شنبه 22 مرداد 1387, 09:32 صبح
سلام
منهم هم اکنون دریک پروژه در حال طراحی کاری مشابه هستم اینکار را دارم انجام میدهم :
یک UserControl جدید را از DataGridView ارث بردم
حال اگر کاربر میخواهد یک ستون داشته باشد که متن آن 90 درجه دوران کند کافیست در خاصیت Tag آن ستون ایجاد شده مقدار 90 را وارد کند و درون رویداد CellPainting برکلاس Graphics و متدهای مربوطه متن سلول را 90 درجه دوران میدهم بهترین راهی که به ذهن من رسید این روش بود

رافعی مهدی
سه شنبه 22 مرداد 1387, 13:04 عصر
فرمايش شما صحيح است. منتهي من نمي دانم اين UserControl را از چه كلاسي از كلاسهاي DGV ارث بري كنم. مثلاً در كار شما سلول حاوي متن است، بنابراين مي توان آن را از كلاس DataGridViewTextBoxCell ارث بري كرده و آن را در رويداد CellPainting مديريت كرد. ولي در كاري كه من دارم انجام مي دهم يك UserControl وجود دارد كه نه دكمه است كه از DataGridViewButtonCell ارث بري كند و نه تصوير است كه از DataGridViewImageCell و نه ...
در اينجا اين مسئله وجود دارد كه نمايش UserControl اساساً با مشكل مواجه است، زيرا اگر از هر كلاسي حتي خود DataGridViewCell نيز ارث بري كرده باشد، باز هم در رويداد CellPainting روشي براي نمايش آن پيدا نمي شود.