DataGridView: Need to make Enter key create newline in textbox

S

Steve K

I've got a full day invested in this now and I still can't make it work.
Hopefully someone here can offer some suggestions.

Here is the situation: I have a data entry application and am using a
DataGridView to enter order details. When it comes to the serial
numbers we will use a barcode reader which send a carriage return
character after each barcode is read. We can't change this behavior
(well, we can but it works great in the other 3-4 applications we use)

When a user is entering serial numbers into the serial number cell I
want each scanned serial number to be on it's own line, just like:
abc123
abc456
abc789

I'm able to get this behavior by pressing the SHIFT+ENTER combo but I
can't setup the barcode reader to send this combination.

The solution I've come up with (based on an article I found online
somewhere) is to create my own DGV Cell, Column and EditingControl.

Here is the code for those classes:
<code>
public class PMDDataGridViewTextBoxEditingControl :
DataGridViewTextBoxEditingControl
{
public override bool EditingControlWantsInputKey(Keys keyData, bool
dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Enter:
return true;
}

return base.EditingControlWantsInputKey(keyData,
dataGridViewWantsInputKey);
}

protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Text += Environment.NewLine;
this.Select(this.Text.Length, 0);
}

base.OnKeyDown(e);
}
}

public class PMDMultilinDataGridViewCell : DataGridViewTextBoxCell
{
public override Type EditType
{
get
{
return typeof(PMDDataGridViewTextBoxEditingControl);
}
}
}

public class PMDMultilineDataGridViewColumn : DataGridViewColumn
{
public PMDMultilineDataGridViewColumn()
: base(new PMDMultilinDataGridViewCell())
{
this.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
}
}
</code>

Note that in the EditingControl I am inserting a newline and moving the
cursor to this newline when an enter key is detected.

My question (finally!) is if this is a sound solution? It works, but
feels "hacky" to me and I suspect I may be missing a more elegant solution.

Anyone have any ideas?
 
S

Steve K

to this newline when an enter key is detected.
My question (finally!) is if this is a sound solution? It works, but
feels "hacky" to me and I suspect I may be missing a more elegant solution.

Anyone have any ideas?

Update: I tried adding this code:
<code>
public PMDDataGridViewTextBoxEditingControl()
:base()
{
this.Multiline = true;
}
</code>

This has no effect, I still need to insert the Environment.NewLine
characters.

It's strange, DataGridViewTextBoxEditingControl derives from TextBox,
I'm not clear where the different behavior is being introduced. In
other words, if I create a multiline TextBox control I can press enter
and get a newline, so why with this DGV control is the behavior different?
 
S

Steve K

Steve said:
I've got a full day invested in this now and I still can't make it work.
Hopefully someone here can offer some suggestions.

Here is the situation: I have a data entry application and am using a
DataGridView to enter order details. When it comes to the serial
numbers we will use a barcode reader which send a carriage return
character after each barcode is read. We can't change this behavior
(well, we can but it works great in the other 3-4 applications we use)

When a user is entering serial numbers into the serial number cell I
want each scanned serial number to be on it's own line, just like:
abc123
abc456
abc789

I'm able to get this behavior by pressing the SHIFT+ENTER combo but I
can't setup the barcode reader to send this combination.

The solution I've come up with (based on an article I found online
somewhere) is to create my own DGV Cell, Column and EditingControl.

Here is the code for those classes:
<code>
public class PMDDataGridViewTextBoxEditingControl :
DataGridViewTextBoxEditingControl
{
public override bool EditingControlWantsInputKey(Keys keyData, bool
dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Enter:
return true;
}

return base.EditingControlWantsInputKey(keyData,
dataGridViewWantsInputKey);
}

protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Text += Environment.NewLine;
this.Select(this.Text.Length, 0);
}

base.OnKeyDown(e);
}
}

public class PMDMultilinDataGridViewCell : DataGridViewTextBoxCell
{
public override Type EditType
{
get
{
return typeof(PMDDataGridViewTextBoxEditingControl);
}
}
}

public class PMDMultilineDataGridViewColumn : DataGridViewColumn
{
public PMDMultilineDataGridViewColumn()
: base(new PMDMultilinDataGridViewCell())
{
this.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
}
}
</code>

Note that in the EditingControl I am inserting a newline and moving the
cursor to this newline when an enter key is detected.

My question (finally!) is if this is a sound solution? It works, but
feels "hacky" to me and I suspect I may be missing a more elegant solution.

Anyone have any ideas?


If anyone is interested my current revision of the above solution works
pretty well. You could do plenty to make it better, but for me it does
the job.

Here is the code:
<code>
namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxCell :
DataGridViewTextBoxCell
{
public override Type EditType
{
get
{
return
typeof(PMDDataGridViewMultiLineTextBoxEditingControl);
}
}
}
}

namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxColumn : DataGridViewColumn
{
public PMDDataGridViewMultiLineTextBoxColumn()
: base(new PMDDataGridViewMultiLineTextBoxCell())
{
this.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
}
}
}

namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxEditingControl :
DataGridViewTextBoxEditingControl
{
private const int MAX_DISPLAY_LINES = 5;
private readonly int _lineHeight = 0;

public PMDDataGridViewMultiLineTextBoxEditingControl()
: base()
{
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
_lineHeight = Convert.ToInt32(g.MeasureString("T",
this.Font).Height);
}

this.Multiline = true;
this.AcceptsReturn = true;
}

public override bool EditingControlWantsInputKey(Keys keyData,
bool dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Enter:
return true;
}

return base.EditingControlWantsInputKey(keyData,
dataGridViewWantsInputKey);
}

protected override void OnGotFocus(EventArgs e)
{
SetRowHeight();
base.OnGotFocus(e);
}

private void SetRowHeight()
{
int numLinesToShow = Math.Min(NumLines, MAX_DISPLAY_LINES);
int rowHeight = Math.Max((int)(numLinesToShow *
_lineHeight), this.EditingControlDataGridView.RowTemplate.Height);


this.EditingControlDataGridView.Rows[this.EditingControlRowIndex].Height
= rowHeight;
}

protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Text += Environment.NewLine;
this.Select(this.Text.Length, 0);

int numLines = NumLines;

if (NumLines < MAX_DISPLAY_LINES)
{
this.ScrollBars = ScrollBars.None;
}
else
{
this.ScrollBars = ScrollBars.Vertical;
}

SetRowHeight();
this.ScrollToCaret();
}

base.OnKeyDown(e);
}

private int NumLines
{
get
{
return this.Text.Split(new string[] {
Environment.NewLine }, StringSplitOptions.None).Length;
}
}

protected override void OnValidated(EventArgs e)
{
// remove any trailing whitespace
//this.Text = this.Text.Trim();
base.OnValidated(e);
}
}
}
</code>

Please, if you see anything that could be better, more efficient, etc.
please let me know.

-Steve
 
Joined
Oct 28, 2008
Messages
1
Reaction score
0
But...

Hi,

How to use this code in DataGridView?

Thanks.

Steve K said:
Steve K wrote:
> I've got a full day invested in this now and I still can't make it work.
> Hopefully someone here can offer some suggestions.
>
> Here is the situation: I have a data entry application and am using a
> DataGridView to enter order details. When it comes to the serial
> numbers we will use a barcode reader which send a carriage return
> character after each barcode is read. We can't change this behavior
> (well, we can but it works great in the other 3-4 applications we use)
>
> When a user is entering serial numbers into the serial number cell I
> want each scanned serial number to be on it's own line, just like:
> abc123
> abc456
> abc789
>
> I'm able to get this behavior by pressing the SHIFT+ENTER combo but I
> can't setup the barcode reader to send this combination.
>
> The solution I've come up with (based on an article I found online
> somewhere) is to create my own DGV Cell, Column and EditingControl.
>
> Here is the code for those classes:
>
> public class PMDDataGridViewTextBoxEditingControl :
> DataGridViewTextBoxEditingControl
> {
> public override bool EditingControlWantsInputKey(Keys keyData, bool
> dataGridViewWantsInputKey)
> {
> switch (keyData & Keys.KeyCode)
> {
> case Keys.Prior:
> case Keys.Next:
> case Keys.End:
> case Keys.Home:
> case Keys.Left:
> case Keys.Up:
> case Keys.Right:
> case Keys.Down:
> case Keys.Delete:
> case Keys.Enter:
> return true;
> }
>
> return base.EditingControlWantsInputKey(keyData,
> dataGridViewWantsInputKey);
> }
>
> protected override void OnKeyDown(KeyEventArgs e)
> {
> if (e.KeyCode == Keys.Enter)
> {
> this.Text += Environment.NewLine;
> this.Select(this.Text.Length, 0);
> }
>
> base.OnKeyDown(e);
> }
> }
>
> public class PMDMultilinDataGridViewCell : DataGridViewTextBoxCell
> {
> public override Type EditType
> {
> get
> {
> return typeof(PMDDataGridViewTextBoxEditingControl);
> }
> }
> }
>
> public class PMDMultilineDataGridViewColumn : DataGridViewColumn
> {
> public PMDMultilineDataGridViewColumn()
> : base(new PMDMultilinDataGridViewCell())
> {
> this.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
> }
> }
>
>
> Note that in the EditingControl I am inserting a newline and moving the
> cursor to this newline when an enter key is detected.
>
> My question (finally!) is if this is a sound solution? It works, but
> feels "hacky" to me and I suspect I may be missing a more elegant solution.
>
> Anyone have any ideas?



If anyone is interested my current revision of the above solution works
pretty well. You could do plenty to make it better, but for me it does
the job.

Here is the code:

namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxCell :
DataGridViewTextBoxCell
{
public override Type EditType
{
get
{
return
typeof(PMDDataGridViewMultiLineTextBoxEditingControl);
}
}
}
}

namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxColumn : DataGridViewColumn
{
public PMDDataGridViewMultiLineTextBoxColumn()
: base(new PMDDataGridViewMultiLineTextBoxCell())
{
this.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
}
}
}

namespace PMD.Library.WinFormControls
{
public class PMDDataGridViewMultiLineTextBoxEditingControl :
DataGridViewTextBoxEditingControl
{
private const int MAX_DISPLAY_LINES = 5;
private readonly int _lineHeight = 0;

public PMDDataGridViewMultiLineTextBoxEditingControl()
: base()
{
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
_lineHeight = Convert.ToInt32(g.MeasureString("T",
this.Font).Height);
}

this.Multiline = true;
this.AcceptsReturn = true;
}

public override bool EditingControlWantsInputKey(Keys keyData,
bool dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
case Keys.Enter:
return true;
}

return base.EditingControlWantsInputKey(keyData,
dataGridViewWantsInputKey);
}

protected override void OnGotFocus(EventArgs e)
{
SetRowHeight();
base.OnGotFocus(e);
}

private void SetRowHeight()
{
int numLinesToShow = Math.Min(NumLines, MAX_DISPLAY_LINES);
int rowHeight = Math.Max((int)(numLinesToShow *
_lineHeight), this.EditingControlDataGridView.RowTemplate.Height);


this.EditingControlDataGridView.Rows[this.EditingControlRowIndex].Height
= rowHeight;
}

protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Text += Environment.NewLine;
this.Select(this.Text.Length, 0);

int numLines = NumLines;

if (NumLines < MAX_DISPLAY_LINES)
{
this.ScrollBars = ScrollBars.None;
}
else
{
this.ScrollBars = ScrollBars.Vertical;
}

SetRowHeight();
this.ScrollToCaret();
}

base.OnKeyDown(e);
}

private int NumLines
{
get
{
return this.Text.Split(new string[] {
Environment.NewLine }, StringSplitOptions.None).Length;
}
}

protected override void OnValidated(EventArgs e)
{
// remove any trailing whitespace
//this.Text = this.Text.Trim();
base.OnValidated(e);
}
}
}


Please, if you see anything that could be better, more efficient, etc.
please let me know.

-Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top