First column of GridView readonly unless new row - vb.net

I have a GridView with various columns and rows pulled from a database.
In the first column I have a dateEdit repository item.
What I would like to do is have this first column readonly for all rows except when the user clicks "Add new row" as the user will need to edit the date on new rows.
I have been trying using the ShowingEditor() event and e.Cancel however this makes the whole row readonly and not just the first column (the rows have other repository items like TextEdits).
I am using DevExpress with Visual Basic and Visual Studio 2019.

In ShowingEditor event you can use FocusedColumn property to set e.Cancel = True only for particular columns.
If YourGridView.FocusedColumn.FieldName = "YourDateEditColumn" Then
e.Cancel = True
Exit Sub
End If

Related

Disallowing textbox editing if a ComboBox in the same Form is not filled (for each row individually) [duplicate]

I am working on an Access 2010 form which where the user can select a record in the form header via a combobox and then build up elements related to the selected record in the detail section of the form. The default view of the form is set to continuous forms.
One of the controls in the detail section of the form is a combobox control. What I want to do is set the enabled property of a textbox on the same row of the form to false based upon a selection from the combobox. The code I am running is:
If Me.cboElementType = "Contract Shrink" Then
Me.txtElementID = ""
Me.txtElementID.Enabled = False
EndIf
This works, but it sets all instances of the textbox (txtElementID) to enabled = false. What I want to have happen is for the txtElementID to have a different enabled setting for each row in the detail section based upon the selection of the combobox cboElementType. So, if cboElementType = "Contract Shrink" on row 1 of the scrolling detail section, the txtElementID.Enabled would be set to false for that row. If cboElementType = "Cost Group" on row 2 of the scrolling detail section, then I'd like txtElementID.Enabled to be False on row 1 of the detail section and txtElementID.Enabled to be True on row 2.
Can anyone confirm or deny that this can be done and, if it can be done, how you would suggest it be accomplished? No matter which way this goes, thanks for help.
You cannot do it through VBA like you did, you need to use Conditional formatting, there you have an option to set the Enabled property.
try in Form_Current() event like
Private Sub Form_Current()
If Me.cboElementType = "Contract Shrink" Then
Me.txtElementID = ""
Me.txtElementID.Enabled = False
EndIf
end sub
I have been searching for days for how to access an individual record on continuous form and I am willing to say it is not possible, but I have a trick that I will share here. I have an investments database, user gets in and writes a proposal and then there is a meeting where either the project is approved (given money) or it is cancelled. However, there are many more states a project can be in, Proposal, Execution, etc. but only Approved/Cancelled can happen at this stage. I created a MockBool field in the Project table. I put that on the continuous form and when the form is closed I run this:
rs_frm=me.recordset
rs_frm.movefirst
while not(rs_frm.eof)
if rs_frm("MockBool") then
rs_frm.edit
rs_frm("ProcessStatus")="Cancelled"
rs_frm("MockBool")=false
rs_frm.update
end if
rs_frm.movenext
wend
I had days of searching and had an epiphany so I thought I would share.

Two Mandatory Fields on a new record but want to search from combobox

I'm relatively new to this and can't figure out how to fix this problem.
I have a form that opens to a new record with two mandatory fields (txtIDNumber and txtDependentCode) and the cursor is in txtIDNumber. On Exit for this field there is code in case data has not been entered:
Private Sub txtIDNumber_Exit(Cancel As Integer)
If IsNull(Me.txtIDNumber) Then
MsgBox "This is a mandatory field."
DoCmd.CancelEvent
End If
Me.txtIDNumber.SetFocus
End Sub
I also have a combobox that allows searching for records on this form. That is where the problem is. If I want to search and not enter a new record I can't because the mandatory field message appears when I try to click the combobox because I have a new record open and didn’t enter the mandatory fields.

MS Access Can't go to specified record because of another control's VB where clause

I have a lookup listbox which is programmed to allow the user to find a specific record/help topic from the list and view it. Now when the list box is used the where clause locks in the record and the first, previous, next, last buttons freeze up and you cannot use them to go to a record. Is there a way to free up the functionality of the buttons to navigate through the records along with the where clause to select.
Here is the code that operates the listbox selections:
Private Sub List35_AfterUpdate()
Dim myTopic As String
myTopic = "Select * from FormsHelpTable where ([ID] = " & Me.List35 & ")"
Me.Form.RecordSource = myTopic
Me.Comment.Requery
End Sub
I believe since the where clause locks in the selection in the box it does not allow navigation from other controls to interfere. What might be a way around this?
You get the runtime error:
You can't go to specified record.
It appears not to be reading the other record in the source table named Help once it updates using the listbox.
Instead of changing the recordset (this is the 'pool' of records which the form could display), you just need to go to the record the user selects from the listbox.
Method 1 (probably the easiest way if your listbox is in the same order as the records of your form)
Use this code:
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
End Sub
You need to ensure that:
The recordset of the form is ordered the same as the listbox. So, for example, you could order both by ID, or by Title.
Note that the +1 comes from the fact that the ListIndex starts at 0, whereas the record indexes start at 1.
Method 2
Ensure each record's Title is unique (set No Duplicates on this field).
Change your listbox to return the Title of the record, rather than it's ID.
Then use this:
Private Sub lstSelect_AfterUpdate()
Me.Title.SetFocus
DoCmd.FindRecord Me.lstSelect
Me.lstSelect.SetFocus
End Sub
Things to note:
It works by searching the field with focus for the string specified. That's why we have to SetFocus on the Title textbox on our form.
We could use ID instead, (which would mean we could have duplicate titles if we wanted), but then we would have to have an ID control on the form to SetFocus to. You can't hide this control either, because it needs to have focus whilst using FindRecord.
Update: Method 1 with reverse-selection
Add an Event Procedure in the Form_Current event, with this code. Then update the code in the lstSelect_AfterUpdate procedure as shown after.
Private Sub Form_Current()
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Note that, depending on how your lstSelect is set up, it may be Column(1, Form.CurrentRecord - 1) instead. Read on for details!
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Explanation of new lines:
The Form_Current event fires every time we go to a new record. We need to look at the index of the record (ie. the position of it in the recordset), which we get by using Form.CurrentRecord. We then want to make the listbox select that record. However, we can't use me.lstSelect.ListIndex as before, because that is a read-only property (we can access it to read it, but we can't set it).
Therefore, we use me.lstSelect.Column(colNum,rowNum) instead, where we specify a column number and a row number. If your listbox has two columns (eg. ID and Title), we want to choose the second column. The index starts at 0, so we would use a value of 1. If, like my lstSelect, you only have one column (Title) then we use 0. Note: it doesn't matter if a column is hidden (ie. has width 0). It still 'counts'.
The row number is Form.CurrentRecord - 1. Remember that the forms recordset index starts at 1, but the index of our listbox starts at 0; hence the - 1.
So why do we need a duplicate of this new row in the AfterUpdate event? Try and comment it out to see what happens if we don't put it in. It's has to do with the Form_Current event firing after we use the listbox.
I fixed this issue with a union clause in the SQL lookup code. The UNION ALL clause and the following union on the table used in the other part had allowed all the records to be used.

Is there a way to allow only unique values in a column of an Infragistics UltraWinGrid?

I'm using an Infragistics UltraWinGrid with a column of drop-down boxes. I don't want the user to be able to select the same value for multiple rows in that column. Is there a simple (or heck, I'd settle for advanced) way to do this?
I'm using VB.NET
-EDIT-
I tried setting a filter on the data source for the drop-down box. But when I did that, the values in the other boxes in that column started disappearing (not the values themselves, but the descriptions that they were supposed to represent, so instead of reading "Information", it just said "1"). All of the cells in a column refer to the same combo box, so if you filter out a value from the data source for one of them, you filter it out for all of them.
I'm currently trying to catch a CellChange event and check against all other currently-used values. If it was already used, I would put up a message saying as much and revert back to the old value. However, the value comes back as the previously-saved one, so... not helpful. About to see if I can use the "text" property.
Since you're using Infragistics, you could use an UltraDropDown which is bound to a DataTable (or something similiar) which you can add a "Selected" column in addition to a column holding the values you want to show.
As each value is selected (via AfterCellUpdate or AfterCellListCloseUp for instance), you could update the "Selected" column in that data source and use a column filter to only show items which haven't been marked as selected. That way as items are selected or removed, the contents of the drop-down would be automatically updated.
To clear the selected flag from the old value, you can use the BeforeCellUpdate event to access the cell's current value then perform a lookup on the data source bound to the UltraDropDown using that value to clear the flag.
Solved it:
The trick was to use BeforeCellUpdate whose BeforeCellUpdateEventArgs has a "NewValue" and a "Cancel" member. I just look through all of the items in the column to see if any of them match the new value. If one does, I notify the user and cancel the operation.
And that's it. Here's the code:
Private Sub myUltraWinGrid_BeforeCellUpdate(ByVal sender As Object, ByVal e As Infragistics.Win.UltraWinGrid.BeforeCellUpdateEventArgs) Handles myUltraWinGrid.BeforeCellUpdate
If e.Cell.Column.Key = "myColumn" Then
Dim newValue As Integer = CInt(e.NewValue)
For Each row As Infragistics.Win.UltraWinGrid.UltraGridRow In myUltraWinGrid.Rows
If row.Cells("myColumn") IsNot e.Cell _ 'So I'm not checking against the current cell
AndAlso CInt(row.Cells("myColumn").Value) = newValue Then
MsgBox("That value has already been used in this column")
e.Cancel = True
End If
Next
End If
End Sub

Problem with datagridview and AddNew

I've created a VB 2008 program to track work requests. It all works perfectly on a VISTA box, but I am having an issue with the program on an XP environment with adding new records.
Basically I've got 2 tabs: TAB 1 holds a datagridview with limited info and a calendar. Selecting dates on the calendar change the info in the datagridview. TAB 2 holds all the available info for that record in text/combo boxes. Both the datagridview and text boxes use the same Binding Source, so they are always in sync whenever the user selects a row from the datagridview. When you select the NEW button, TAB 2 appears with all the text boxes empty so the user can add data. If you look back on TAB 1, you see an empty, new row added to the datagridview (user can not directly add a row in the datagridview as AllowUserToAdd is set to false). If you let the app stay in the AddNew record state on VISTA, you remain on that new record until you select SAVE or CANCEL. On XP, however, after 1 minute time lapse, all the empty fields will eventually fill in with an existing record for that particular calendar day. When you look back on TAB 1, you no longer see the new empty row, you only see existing records previously saved.
Any ideas on how to resolve?? Thanks for any assistance.
Here is the code for adding new records:
Private Sub cmdNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdNew.Click
'Focus on Work tab
TabControl1.SelectedTab = tabWork
'Change the files from read-only
bEditMode = True
ChangeEditMode()
'Clear the current information stored in the fields
Try
Me.BindingContext(WorkRequestBindingSource).AddNew()
Catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.Message)
End Try
'Hidden text boxes populate with current selected calendar
'Used to populate TimeIn and DateNeed because if never clicked on, will populate as NULL on save
dtpDateNeed.Text = txtDate.Text
dtpTimeIn.Text = txtTime.Text
End Sub
This is definitely an environmental issue. To solve the problem I would need to know which browsers you are using on each machine and some of the settings on each.
It sounds like the XP machine is refreshing the page after a timeout period and therefore munging the new record. I have seen that happen before and it stinks.
You might need to consider saving some more state information in the viewstate to catch that kind of thing.
If the code is exactly the same I wonder if it is an environment issue e.g. something like different international options or version of framework?