I have a password column in my datagridview, and I'd like to display the characters as a * while editing and even displaying. I have the following code but when saving to the database the password gets saved as ***** for example.:
Code:
Private Sub dgvUsers_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgvUsers.CellFormatting
If dgvUsers.Columns(e.ColumnIndex).Name.Equals("Password") Then
If (Not e.Value Is Nothing) Then
e.Value = New String(CChar("*"), e.Value.ToString.Length)
End If
End If
End Sub
Code:
Private Sub dgvUsers_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvUsers.EditingControlShowing
If (CType(sender, DataGridView).CurrentCell.ColumnIndex <> 4) Then
If (CType(sender, DataGridView).CurrentCell.ColumnIndex = 3) Then
CType(e.Control, TextBox).PasswordChar = CChar("*")
Else
CType(e.Control, TextBox).PasswordChar = Char.MinValue
End If
End If
End Sub
It looks like setting e.Value actually sets the Value of the cell itself, which is obviously not what you want. I'd suggest creating your own DataGridViewPasswordTextBoxColumn and DataGridViewPasswordTextBoxCell classes. They would inherit the existing text box classes and there would be very little to change. The main thing would be that you could override the GetFormattedValue method and return a string of mask characters without changing the actual value of the cell. You could also provide a PasswordChar property on the column that would propagate down to the cells and editing control.
Hi JM, this is my class so far. I don't understand this, please help me:
The main thing would be that you could override the GetFormattedValue method and return a string of mask characters without changing the actual value of the cell. You could also provide a PasswordChar property on the column that would propagate down to the cells and editing control
Code:
Imports System
Imports System.Windows.Forms
Public Class DataGridViewPasswordTextBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New PasswordTextboxCell)
End Sub
Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As System.Windows.Forms.DataGridViewCell)
If value IsNot Nothing AndAlso _
Not value.GetType.IsAssignableFrom(GetType(PasswordTextboxCell)) _
Then
Throw New InvalidCastException("Must be TextboxCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class PasswordTextboxCell
Inherits DataGridViewTextBoxCell
Public Sub New()
Me.Value = ""
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim ctl As PasswordTextBoxEditingControl = _
CType(DataGridView.EditingControl, PasswordTextBoxEditingControl)
If IsDBNull(Me.Value) Then
ctl.Text = ""
Else
ctl.Text = CType(Me.Value, String)
End If
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing contol that CalendarCell uses.
Return GetType(PasswordTextBoxEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return String.Empty
End Get
End Property
End Class
Public Class PasswordTextBoxEditingControl
Inherits TextBox
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
End Sub
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) _
Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
End Sub
Public Property EditingControlDataGridView() As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As System.Windows.Forms.DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlFormattedValue() As Object _
Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Text
End Get
Set(ByVal value As Object)
If TypeOf value Is String Then
Me.Text = CStr(value)
End If
End Set
End Property
Public Property EditingControlRowIndex() As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey
End Function
Public ReadOnly Property EditingPanelCursor() As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor
Get
End Get
End Property
Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Text
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnTextChanged(e)
End Sub
End Class
The GetFormattedValue method of a DataGridViewCell takes the actual value that the cell contains and processes it, returning a formatted value for display in the UI. This will allow you to return a string containing password mask characters for display without changing the actual value of the cell.
I could be wrong but I'd also expect that it would be easier to inherit DataGridViewTextBoxEditingControl than to inherit TextBox and provide your own implementation of IDataGridViewEditingControl.
I've done it . Thank you JM. I ain't sure if my class is 100% correct but it works. Here is the class incase anyone else ever needs it. I've also provided a masked property for the editing control. JM if you could please check this class and point out any faults i would greatly appreciate it:
Code:
Imports System
Imports System.Windows.Forms
Public Class DataGridViewPasswordTextBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New PasswordTextboxCell)
End Sub
Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As System.Windows.Forms.DataGridViewCell)
If value IsNot Nothing AndAlso _
Not value.GetType.IsAssignableFrom(GetType(PasswordTextboxCell)) _
Then
Throw New InvalidCastException("Must be TextboxCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class PasswordTextboxCell
Inherits DataGridViewTextBoxCell
Public Sub New()
Me.Value = ""
End Sub
Protected Overrides Function GetFormattedValue(ByVal value As Object, ByVal rowIndex As Integer, ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal valueTypeConverter As System.ComponentModel.TypeConverter, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object
Dim strVal As String
strVal = New String(CChar("*"), value.ToString.Length)
Return MyBase.GetFormattedValue(strVal, rowIndex, cellStyle, valueTypeConverter, formattedValueTypeConverter, context)
End Function
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim ctl As PasswordTextBoxEditingControl = _
CType(DataGridView.EditingControl, PasswordTextBoxEditingControl)
If IsDBNull(Me.Value) Then
ctl.Text = ""
Else
ctl.Text = CType(Me.Value, String)
ctl.PasswordChar = "*"
ctl.Mask = "*"
End If
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing contol that CalendarCell uses.
Return GetType(PasswordTextBoxEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return ""
End Get
End Property
End Class
Public Class PasswordTextBoxEditingControl
Inherits TextBox
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
End Sub
Private m_strMask As String
Public Property Mask() As String
Get
Return m_strMask
End Get
Set(ByVal value As String)
m_strMask = value
End Set
End Property
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) _
Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
End Sub
Public Property EditingControlDataGridView() As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As System.Windows.Forms.DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlFormattedValue() As Object _
Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Text
End Get
Set(ByVal value As Object)
If TypeOf value Is String Then
Me.Text = CStr(value)
End If
End Set
End Property
Public Property EditingControlRowIndex() As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey
End Function
Public ReadOnly Property EditingPanelCursor() As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor
Get
End Get
End Property
Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Text
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnTextChanged(e)
End Sub
End Class
vb.net usage:
Code:
Dim passwordtextboxcolumn As New DataGridViewPasswordTextBoxColumn
With passwordtextboxcolumn
.HeaderText = "Password"
.DataPropertyName = "Password"
End With
Well done. Maybe you're better with classes than you thought and you posted asking for help a bit prematurely.
That said, you've probably done more than is required. For instance, there's no need for your custom editing control because the DataGridViewTextBoxEditingControl class already supports the functionality you need. Here's my version that I was preparing in the mean time:
vb.net Code:
Imports System.ComponentModel
Public Class DataGridViewPasswordTextBoxColumn
Inherits DataGridViewColumn
Private _passwordChar As Char
Private _useSystemPasswordChar As Boolean
<Category("Password")>
Public Property PasswordChar As Char
Get
Return _passwordChar
End Get
Set
If _passwordChar <> Value Then
_passwordChar = Value
Dim cell = TryCast(CellTemplate, DataGridViewPasswordTextBoxCell)
If cell IsNot Nothing Then
'Update the template cell.
cell.PasswordChar = Value
End If
If DataGridView IsNot Nothing Then
'Update each existing cell in the column.
For Each row As DataGridViewRow In DataGridView.Rows
Note that they can also be added to your grid in the designer.
EDIT: I have fixed a bug in the DataGridViewPasswordTextBoxCell where editing a second time would cause the mask characters to be stored instead of the original characters they were masking. The solution was to change the first line of the InitializeEditingControl method from this:
The provided solution is the best that I have ever seen!
PS: Maybe one slight modification: Because Textbox think '*' instead of the big black dot as the "SystemPasswordChar", the last sentence in "InitializeEditingControl" may be changed to ".UseSystemPasswordChar = false" to be controlled totally by the customerized class.
Maybe one slight modification: Because Textbox think '*' instead of the big black dot as the "SystemPasswordChar", the last sentence in "InitializeEditingControl" may be changed to ".UseSystemPasswordChar = false" to be controlled totally by the customerized class.
No, that's not a good idea. The way I've done it the mask character is already controlled by the values the user sets in the column properties. That method is simply applying those property values to the edting control, which is exactly what should happen.
I will use the code you (Nitesh & JMcilhinney) had proposed to implemente the "Password char on DataGrid Column" problem. I like the way you code (the way I want become to code ). I have not tested it, but in case that It works the way I want, I want to quote in my code credits to you (both). Please (If u want) send me e-mail or VbForums Contact.
Could you please show me one example how to use the class in my code?
Thanks and regards,
Treya
They get used exactly the same way as any other DataGridViewColumn. Once you've added the classes to your project and built it, you can then add a column to your grid and select DataGridViewPasswordTextBoxColumn as the type. You can then set its properties just like any other column type.
But i got "Conversion from type 'DBNull' to type 'String' is not valid." error.
i can only add on error resume next handle on top of
Protected Overrides Function GetFormattedValue
Any advise for this error would be much appreciated.
But i got "Conversion from type 'DBNull' to type 'String' is not valid." error.
i can only add on error resume next handle on top of
Protected Overrides Function GetFormattedValue
Any advise for this error would be much appreciated.
Regards,
Treyacon
Hmmm... maybe I didn't ever test it with null values. Try changing CStr(value) to value.ToString()
Hello there.
I know this thread is really old and that I'm necroing this old treasure, but I'm not understanding how to use the classes mentioned here, even though I have tried, but nothing changed.
This is what I have:
Code:
Try
Dim passwordtextboxcolumn As New DataGridViewPasswordTextBoxColumn
With passwordtextboxcolumn
.HeaderText = "Password"
.DataPropertyName = "Password"
End With
taLogins.Fill(tLogins)
dgvLoginsList.DataSource = tLogins
dgvLoginsList.Columns.Add(passwordtextboxcolumn)
dgvLoginsList.Columns(2).Visible = False
dgvLoginsList.Columns(7).DisplayIndex = 2
Label2.Text = "Utilizadores: " & tLogins.Rows.Count
Catch ex As Exception
End Try
So, I basically have a tableadapter "taLogins", that will load data into the table "tlogins". Then, I display the data on datagridview, from that table.
This will, of course, generate named columns and on this case a column named Password will be add on the datagridview.
To my sense (and I don't know if I'm going the right path here) after adding the column "passwordtextboxcolumn", I hide the already name column "Password" and set the índex of the added column as the same as the one I've just hidden.
By doing this process I get the column, with overridable properties written on the classes on the desired índex. Although, I still have the data on this column being showed as plain text, instead of the "*" mask as it was supposed...
I hope I was able to explain my problem and hope that someone would please explain to me what I need to do.
Edit* Damn, I feel stupid now. I just noticed I needed to add the following line:
passwordtextboxcolumn.PasswordChar = "*"
It's working wonders now.
Last edited by Simbiose; Mar 31st, 2014 at 07:03 AM.
Ok, I see what you're saying. The code works the same without 'new'.
I thought it was working perfectly, but with further testing...
If doubleclicking a cell to copy it (see code below), it then makes every cell UseSystemPasswordChar while typing. It reverts to normal text when clicking elsewhere. I don't get it.
Code:
Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles MyGrid.CellDoubleClick
Dim cell As DataGridViewCell = MyGrid.CurrentCell
If Not IsDBNull(cell.Value) And Not cell.Value.ToString = "" And Not cell.Value Is Nothing Then
Select Case e.ColumnIndex
Case 5
Exit Sub
Case 2
If Not cell.Value.startswith("http://") And Not cell.Value.startswith("https://") Then
cell.Value = "http://" & cell.Value
End If
Process.Start(cell.Value)
Case Else
If cell.Value.ToString IsNot Nothing Then
My.Computer.Clipboard.SetText(cell.Value.ToString)
End If
End Select
End If
End Sub
I can't figure out if the problem is this sub, mousedown, or mouseup.
Last edited by Amerigoware; Apr 16th, 2018 at 10:01 AM.
@Amerigoware, because of the age of this thread and the fact that it was marked Resolved, I suggested to the mods that your posts be moved to their own thread, which was done. You've now posted here again with zero context. The thread created for you is here.