Winform里实现一个双击ListBox可以切换为TextBox编辑的效果

      在Winform窗体上我们有时候会使用ListBox来展示数据,但是有时候我们希望能对ListBox里的数据进行编辑。通常我们可能会采用双击ListBox的Item后弹出一个InputBox来实现,不过我希望能来的直接一点,正如我标题上说的,双击ListBox后,将ListBox整个切换为TextBox,原来的ListBox里的文本在TextBox里通过换行显示。最终得到的效果如下面的GIF动图。

      Winform里实现一个双击ListBox可以切换为TextBox编辑的效果

      我写了一个ListBoxEditor的类,类代码如下所示。其主要是监听ListBox的双击鼠标事件,创建一个文本框控件,将ListBox控件的Item字符串值写入TextBox中。在文本框中双击或者文本框失去焦点时,重新切换为ListBox控件。

ListBoxEditor.cs

public class ListBoxEditor
{
    public ListBoxEditor(ListBox listBox,string itemSplitter=";") { ListBox = listBox; ItemSplitter = itemSplitter; }

    private ListBox _listBox;
    public ListBox ListBox {
        get { return _listBox; }
        set {
            _listBox = value;
            if (_listBox != null) {
                _listBox.MouseDoubleClick += ListBoxMouseDoubleClick;
            }
        }
    }

    private string _itemSplitter;
    public string ItemSplitter {
        get { return _itemSplitter; }
        set { _itemSplitter = value; }
    }

    private TextBox _txtBox;
    private void ListBoxMouseDoubleClick(object sender, MouseEventArgs e)
    {
        if (_txtBox == null){ _txtBox = new TextBox(); }
        string str = null;
        for (int i = 0; i < ListBox.Items.Count; i++) {
            if (i == 0) { str = ListBox.Items[i].ToString(); }
            else { str += ItemSplitter + ListBox.Items[i].ToString(); }
        }

        _txtBox.Font = ListBox.Font;
        _txtBox.Multiline = true;
        _txtBox.WordWrap = true;
        _txtBox.ScrollBars = ScrollBars.Vertical;
        _txtBox.Text = str;
        ListBox.Parent.Controls.Add(_txtBox);
        _txtBox.Location = ListBox.Location;
        _txtBox.Size = ListBox.Size;
        _txtBox.Visible = true;
        _txtBox.BringToFront();
        _txtBox.LostFocus += TextBoxLostFocus;
        _txtBox.MouseDoubleClick += TextBoxMouseDoubleClick;
        _txtBox.Focus();
    }

    private void TextBoxMouseDoubleClick(object sender, MouseEventArgs e)
    {
        CloseTextBox();
    }

    private void TextBoxLostFocus(object sender, EventArgs e)
    {
        CloseTextBox();
    }

    private void CloseTextBox() {
        string[] strs = Regex.Split(_txtBox.Text, ItemSplitter, RegexOptions.IgnoreCase);
        ListBox.DataSource = null;
        if (strs != null && strs.Count() > 0)
        {
            ListBox.DataSource= strs;
        }
        ListBox.Parent.Controls.Remove(_txtBox);
        _txtBox = null;
    }
}

      使用方法:在需要实现ListBox双击使用文本框进行编辑的窗体中,使用如下的代码来启用功能:

public frmSysSetting()
{
    InitializeComponent();
    editor = new ListBoxEditor(lstMailTo, Environment.NewLine);//为收件人列表框初始化一个编辑器,分隔符为换行符
}