創建可編輯ListView控件
ListView控件是一個在Windows應用程序中使用頻率比較高的一個,通常使用它來顯示數據報表。很多情況下,我們不僅僅使用ListView來顯示數據,還要求編輯其中的數據。但是.NET提供的ListView控件的編輯功能十分有限,只能編輯首列,編輯格式只能爲文本框,等等,使用起來甚爲不便。因此本人新寫了一個類,擴充了其功能,客戶程序員可以設置任何列的格式(只讀,編輯狀態下文本框,編輯狀態下組合框), 代碼如下:
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
1.ALAN_ListViewColumnStyle 列風格枚舉
/// <summary>
/// 列風格枚舉
/// </summary>
public enum ALAN_ListViewColumnStyle
{
ReadOnly, //只讀
EditBox, //編輯狀態下顯示爲文本框
ComboBox //編輯狀態下顯示爲組合框
};
2.ALAN_ColumnHeader 帶有自定義風格的列
/// <summary>
/// 列描述
/// </summary>
public class ALAN_ColumnHeader : ColumnHeader
{
private ALAN_ListViewColumnStyle cs; //本列的風格
public ALAN_ColumnHeader() : base()
{
cs = ALAN_ListViewColumnStyle.ReadOnly;
}
public ALAN_ColumnHeader(ALAN_ListViewColumnStyle _cs)
{
cs = _cs;
}
public ALAN_ListViewColumnStyle ColumnStyle
{
get { return cs; }
set { cs = value;}
}
}
3.ALAN_EditListView 列表控件
/// <summary>
/// 可編輯的ListView控件
/// </summary>
public class ALAN_EditListView : ListView
{
private ListViewItem m_currentLVItem;
private int m_nX=0;
private int m_nY=0;
private string m_strSubItemText ;
private int m_nSubItemSelected = 0 ;
private ComboBox[] m_arrComboBoxes = new ComboBox[20];
private System.Windows.Forms.TextBox editBox;
private Font m_fontComboBox;
private Font m_fontEdit;
private Color m_bgcolorComboBox;
private Color m_bgcolorEdit;
public ALAN_EditListView()
{
editBox = new System.Windows.Forms.TextBox();
this.ComboBoxFont = this.Font;
this.EditFont = this.Font;
this.EditBgColor = Color.LightBlue;
this.m_bgcolorComboBox = Color.LightBlue;
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.SMKMouseDown);
this.DoubleClick += new System.EventHandler(this.SMKDoubleClick);
this.GridLines = true ;
editBox.Size = new System.Drawing.Size(0,0);
editBox.Location = new System.Drawing.Point(0,0);
this.Controls.AddRange(new System.Windows.Forms.Control[] {this.editBox});
editBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.EditOver);
editBox.LostFocus += new System.EventHandler(this.FocusOver);
editBox.AutoSize = true;
editBox.Font = this.EditFont;
editBox.BackColor = this.EditBgColor;
editBox.BorderStyle = BorderStyle.FixedSingle;
editBox.Hide();
editBox.Text = "";
}
public Font ComboBoxFont
{
get { return this.m_fontComboBox; }
set { this.m_fontComboBox = value;}
}
public Color ComboBoxBgColor
{
get { return this.m_bgcolorComboBox; }
set
{
this.m_bgcolorComboBox = value;
for(int i=0; i<this.m_arrComboBoxes.Length; i++)
{
if (m_arrComboBoxes[i] != null)
m_arrComboBoxes[i].BackColor = this.m_bgcolorComboBox;
}
}
}
public Font EditFont
{
get { return this.m_fontEdit; }
set
{
this.m_fontEdit = value;
this.editBox.Font = this.m_fontEdit;
}
}
public Color EditBgColor
{
get { return this.m_bgcolorEdit; }
set
{
this.m_bgcolorEdit = value;
this.editBox.BackColor = this.m_bgcolorEdit;
}
}
public void SetColumn(int columnIndex, ALAN_ListViewColumnStyle cs)
{
if (columnIndex<0 || columnIndex>this.Columns.Count)
throw new Exception("Column index is out of range");
((ALAN_ColumnHeader)Columns[columnIndex]).ColumnStyle = cs;
}
public void BoundListToColumn(int columnIndex, string[] items)
{
if (columnIndex<0 || columnIndex>this.Columns.Count)
throw new Exception("Column index is out of range");
if ( ((ALAN_ColumnHeader)Columns[columnIndex]).ColumnStyle != ALAN_ListViewColumnStyle.ComboBox)
throw new Exception("Column should be ComboBox style");
ComboBox newbox = new ComboBox();
for(int i=0; i<items.Length; i++)
newbox.Items.Add(items[i]);
newbox.Size = new System.Drawing.Size(0,0);
newbox.Location = new System.Drawing.Point(0,0);
this.Controls.AddRange(new System.Windows.Forms.Control[] {newbox});
newbox.SelectedIndexChanged += new System.EventHandler(this.CmbSelected);
newbox.LostFocus += new System.EventHandler(this.CmbFocusOver);
newbox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CmbKeyPress);
newbox.Font = this.ComboBoxFont;
newbox.BackColor = this.ComboBoxBgColor;
newbox.DropDownStyle = ComboBoxStyle.DropDownList;
newbox.Hide();
this.m_arrComboBoxes[columnIndex] = newbox;
}
private void CmbKeyPress(object sender , System.Windows.Forms.KeyPressEventArgs e)
{
ComboBox cmbBox = (ComboBox)sender;
if ( e.KeyChar == 13 || e.KeyChar == 27 ) //CR or ESC press
{
cmbBox.Hide();
}
}
private void CmbSelected(object sender , System.EventArgs e)
{
ComboBox cmbBox = (ComboBox)sender;
int sel = cmbBox.SelectedIndex;
if ( sel >= 0 )
{
string itemSel = cmbBox.Items[sel].ToString();
m_currentLVItem.SubItems[m_nSubItemSelected].Text = itemSel;
}
}
private void CmbFocusOver(object sender , System.EventArgs e)
{
ComboBox cmbBox = (ComboBox)sender;
cmbBox.Hide() ;
}
private void EditOver(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if ( e.KeyChar == 13 )
{
m_currentLVItem.SubItems[m_nSubItemSelected].Text = editBox.Text;
editBox.Hide();
}
if ( e.KeyChar == 27 )
editBox.Hide();
}
private void FocusOver(object sender, System.EventArgs e)
{
m_currentLVItem.SubItems[m_nSubItemSelected].Text = editBox.Text;
editBox.Hide();
}
public void SMKDoubleClick(object sender, System.EventArgs e)
{
// Check the subitem clicked .
int nStart = m_nX ; //current mouse down X position
int spos = 0 ;
int epos = this.Columns[0].Width ;
for ( int i=0; i < this.Columns.Count ; i++)
{
if ( nStart > spos && nStart < epos )
{
m_nSubItemSelected = i ;
break;
}
spos = epos ;
epos += this.Columns[i].Width;
}
m_strSubItemText = m_currentLVItem.SubItems[m_nSubItemSelected].Text ;
ALAN_ColumnHeader column = (ALAN_ColumnHeader)Columns[m_nSubItemSelected];
if ( column.ColumnStyle == ALAN_ListViewColumnStyle.ComboBox )
{
ComboBox cmbBox = this.m_arrComboBoxes[m_nSubItemSelected];
if (cmbBox == null)
throw new Exception("The ComboxBox control bind to current column is null");
Rectangle r = new Rectangle(spos , m_currentLVItem.Bounds.Y , epos , m_currentLVItem.Bounds.Bottom);
cmbBox.Size = new System.Drawing.Size(epos - spos , m_currentLVItem.Bounds.Bottom-m_currentLVItem.Bounds.Top);
cmbBox.Location = new System.Drawing.Point(spos , m_currentLVItem.Bounds.Y);
cmbBox.Show() ;
cmbBox.Text = m_strSubItemText;
cmbBox.SelectAll() ;
cmbBox.Focus();
}
if ( column.ColumnStyle == ALAN_ListViewColumnStyle.EditBox )
{
Rectangle r = new Rectangle(spos , m_currentLVItem.Bounds.Y , epos , m_currentLVItem.Bounds.Bottom);
editBox.Size = new System.Drawing.Size(epos - spos , m_currentLVItem.Bounds.Height);
editBox.Location = new System.Drawing.Point(spos , m_currentLVItem.Bounds.Y);
editBox.Show() ;
editBox.Text = m_strSubItemText;
editBox.SelectAll() ;
editBox.Focus();
}
}
public void SMKMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
m_currentLVItem = this.GetItemAt(e.X , e.Y);
m_nX = e.X ;
m_nY = e.Y ;
}
}
}
使用方法如下:
this.listView1 = new ALAN_EditListView();
///////////////////////
///add the columns
ALAN_ColumnHeader header1 = new ALAN_ColumnHeader(ALAN_ListViewColumnStyle.ReadOnly);
header1.Width = 120;
header1.Text = "姓名";
this.listView1.Columns.Add(header1);
ALAN_ColumnHeader header2 = new ALAN_ColumnHeader(ALAN_ListViewColumnStyle.EditBox);
header2.Width = 120;
header2.Text = "性別";
this.listView1.Columns.Add(header2);
ALAN_ColumnHeader header3 = new ALAN_ColumnHeader(ALAN_ListViewColumnStyle.EditBox);
header3.Width = 120;
header3.Text = "年齡";
this.listView1.Columns.Add(header3);
ALAN_ColumnHeader header4 = new ALAN_ColumnHeader(ALAN_ListViewColumnStyle.ComboBox);
header4.Width = 120;
header4.Text = "專業";
this.listView1.Columns.Add(header4);
ALAN_ColumnHeader header5 = new ALAN_ColumnHeader(ALAN_ListViewColumnStyle.ComboBox);
header5.Width = 120;
header5.Text = "輪休";
this.listView1.Columns.Add(header5);
///////////////////////
///bound the combox
this.listView1.BoundListToColumn(3, new string[]{"Lotus", "SQL Server", ".NET", "VB"});
this.listView1.BoundListToColumn(4, new string[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"});
/////////////////////////////////////
///set edit state font and backcolor
//this.listView1.ComboBoxBgColor = Color.LightYellow;
this.listView1.ComboBoxFont = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.listView1.EditFont = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
///////////////////////
///add rows
string[] s = new string[5];
s[0] = "張三" ;
s[1] = "男";
s[2] = "24" ;
s[3] = ".NET" ;
s[4] = "Sun";
this.listView1.Items.Add( new ListViewItem(s));
s[0] = "李四" ;
s[1] = "男";
s[2] = "25" ;
s[3] = "SQL Server" ;
s[4] = "Mon";
this.listView1.Items.Add( new ListViewItem(s));
s[0] = "王五" ;
s[1] = "男";
s[2] = "23" ;
s[3] = "VB" ;
s[4] = "Tue";
this.listView1.Items.Add( new ListViewItem(s));
s[0] = "趙六" ;
s[1] = "女";
s[2] = "22" ;
s[3] = "Lotus" ;
s[4] = "Wed";
this.listView1.Items.Add( new ListViewItem(s));
///////////////////////////
///other common attributs
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listView1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.listView1.FullRowSelect = true;
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(448, 273);
this.listView1.TabIndex = 0;
this.listView1.View = System.Windows.Forms.View.Details;
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.listView1});
雙擊需要編輯的單元,如果該列爲ALAN_ListViewColumnStyle.ReadOnly 則沒有變化;如果該列爲ALAN_ListViewColumnStyle.EditBox則出現文本框;如果該列爲ALAN_ListViewColumnStyle.ComboBox則出現組合框,如下圖:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
圖1 EditBox風格
圖2 ComboBox風格