创建可编辑ListView控件

ListView控件是一个在Windows应用程序中使用频率比较高的一个,通常使用它来显示数据报表。很多情况下,我们不仅仅使用ListView来显示数据,还要求编辑其中的数据。但是.NET提供的ListView控件的编辑功能十分有限,只能编辑首列,编辑格式只能为文本框,等等,使用起来甚为不便。因此本人新写了一个类,扩充了其功能,客户程序员可以设置任何列的格式(只读,编辑状态下文本框,编辑状态下组合框), 代码如下:

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 列表控件

using System.Drawing;
/// <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则出现组合框,如下图:

图1 EditBox风格

图2 ComboBox风格



对该文的评论 人气:588

ruanyuping (2003-11-3 14:06:26)

有没有源码下载啊

steeven (2003-10-31 16:47:48)

能不能解释一下实现方式和要点.一堆代码没时间看啊

Contributors: FHL