您如何阻止用户在TextBox中添加/删除行?

时间:2009-03-02 17:42:02

标签: c# winforms

您如何阻止用户在TextBox中添加或删除行?我的意思是,如果我将文本框中的文本设置为带有一些文本的7行,我怎样才能确保它总是有7行文本?用户必须能够像往常一样编辑这些行,但不能完全删除一行,也不能添加任何新行。

必须考虑键盘输入以及剪切和粘贴等内容。

有什么好主意吗?


原因:我想让文件重命名类似于Oscar's Renamer。你给它一个文件夹,它将文件名加载到一个文本框中,你可以在文本框中进行更改,就像在文本编辑器中一样。当您对更改感到满意时,请将其写回。当然,文本框中常量n行的原因是行n是文件n的名称。不应该允许添加新行,因为您只在该文件夹中包含这些文件。也不允许删除行,因为您将丢失文件的名称。

为什么在它已经存在时会遇到制作这样的东西的麻烦?好吧,我很想知道我是否可以做到这一点,并认为沿途学习一些东西可能是一个很好的练习。因为它有一些需要解决的有趣问题。像这一个:)我认为还有一些功能Oscar's Renamer。所以...总结一下:我正在做这个学习并尝试制作更好的版本。我完全知道我可能也完全失败,或者只是永远不会完成它:p但这是另一个故事。我想学习

6 个答案:

答案 0 :(得分:6)

然后您的数据接口错误。在这种情况下,您应该有固定数量的文本框,每个文本框对应一行。这将允许用户修改每一行的内容,但不能删除一行或添加一行。

尝试创建一个多行文本框这样做最多会让人抓狂,因为您必须确定何时添加/删除新行然后终止更改。

答案 1 :(得分:3)

为什么不使用列表框呢?

答案 2 :(得分:2)

我可能会让用户在文本框中执行他们想要的操作,然后添加验证以向用户显示当他们超过7行时出现错误(例如红色轮廓和工具提示或其他内容)。如果它们在7行以下,没问题,请在处理该数据时添加它们。

您想要总是7行的具体原因是什么?就像casperOne所说,也许您使用的界面并不适合您的需求。

答案 3 :(得分:1)

这样做的一种可能方法是对Textbox控件进行子类化并覆盖winProc方法。此方法处理泵入窗口控件的所有窗口消息(在您的情况下为文本框)。您可以监视退格键的使用并删除键和克拉位置,并丢弃尝试删除回车换行序列的击键。并为用户提供交互式警报,告诉他们为什么不能删除整行。

这样做可以让您完全控制,并且是查看进入Textbox控件的所有输入的最低级别方式。您可以拦截某些消息并将其丢弃,您希望允许的消息只是将它们传递给基类方法。例如,如果用户突出显示所有行并点击删除键。还有其他事件处理程序可用于拦截键盘输入,但它们有一些限制,winProc将允许您检查指向控件的任何消息,包括删除,退格复制和粘贴等,鼠标点击等。

样品:

public class myCustomTextBox : TextBox
{
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 770) // window paste message id
        {
            string clipBoardData = Clipboard.GetDataObject().GetData(DataFormats.Text).ToString();
            handlePasteEvent(clipBoardData);
        }
        else
        {
            base.WndProc(ref m);
        }
    }
    private void handlePasteEvent(string pasteData)
    {
        // process pasted data
    }
}

答案 4 :(得分:1)

既然你已经说过这是一个学习项目,看看我是否可以做项目,我认为你应该投入一些WPF。带有itemtemplate的列表框可以很好地解决这个问题。

如果不这样做,我会考虑使用数据网格而不是文本框。

答案 5 :(得分:0)

将数据加载到可编辑的DataGrid而不是TextBox中,这样可以使事情变得更加简单,并且您还可以选择哪些列可编辑而哪些列不可编辑。

以下是使用DataGridView并模拟文本框的示例:

  • 隐藏网格线。
  • 隐藏列和行的标题。
  • 背景颜色与TexBox的颜色相同。

将DataGridView添加到表单并使用以下代码:

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

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.dataGridView1.AllowUserToResizeRows = false;
            this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            this.dataGridView1.BackgroundColor = SystemColors.Window;
            this.dataGridView1.BorderStyle = BorderStyle.None;
            this.dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None;
            this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.ColumnHeadersVisible = false;
            this.dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;
            this.dataGridView1.MultiSelect = false;
            this.dataGridView1.RowHeadersVisible = false;
            this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);

            dataGridView1.DataSource = Directory.GetFiles(Environment.CurrentDirectory).Select(f => new FileEdit { FileName = Path.GetFileName(f) }).ToList();
        }

        private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            dataGridView1.BeginEdit(true);
        }

    }

    class FileEdit
    {
        public string FileName { get; set; }    
    }
}