DGV combobox displays, but does not choose, default value - vb.net

I'm adding a ComboBoxColumn to my DataGridView and, with BindingSources, linking it to a separate related Department table.
A new row displays the first listed department (Accounts), but it doesn't select it by default, causing the error:
Cannot insert the value NULL into column 'DeptID', table
'StaffDB.dbo.Staff'; column does not allow nulls. INSERT fails.
Following advice from an answer here at SO, I'm using the following to set the defaults:
comboCol.DefaultCellStyle.NullValue = _bsDept(0)("Department")
comboCol.DefaultCellStyle.DataSourceNullValue = _bsDept(0)("DeptID")
This appears to work on debugging, with the values 4 and "Accounts", but still yields the same error.
Here are all the relevant settings for the ComboBox:
Dim comboCol = New DataGridViewComboBoxColumn()
comboCol.DataSource = _bsDept
comboCol.ValueMember = "DeptID"
comboCol.DisplayMember = "Department"
'staff table..
comboCol.DataPropertyName = "DeptID"
comboCol.HeaderText = "Department"
comboCol.DefaultCellStyle.Format = "d"
'the first Department "Accounts" appears to be selected, but it isn't
comboCol.DefaultCellStyle.NullValue = _bsDept(0)("Department")
comboCol.DefaultCellStyle.DataSourceNullValue = _bsDept(0)("DeptID")
dgvStaff.Columns.Add(comboCol)
Why are my default values being ignored?
(The ComboBox works if I choose a Department myself.)

I am not sure those DefaultCellStyle props do more than control how Nulls etc are displayed, given the name. There is a DefaultValuesNeeded event which might be a more appropriate place to set default values. For instance (some code I have handy that does just that):
Private Sub dgv2_DefaultValuesNeeded(sender As Object,
e As DataGridViewRowEventArgs) Handles dgv2.DefaultValuesNeeded
'defaults
e.Row.Cells("Fish").Value = "Cod"
e.Row.Cells("Bird").Value = "Raven"
e.Row.Cells("itemDate").Value = DateTime.Now.Date
End Sub
In your case, you would supply a value from the Department source.

Related

How can I change value in another column based on some other column (v.b dev express)

I am using Grid from devExpress to display some data from database, I also implemented RepositoryItemLookUp because I needed to see some values in my column as dropdowns and here is the code:
`Dim riLookup As New RepositoryItemLookUpEdit()
riLookup.NullText = String.Empty
DataTableDobTableAdapter.FillDob(Me.DsOrders.DataTableDob)
riLookup.DataSource = Me.DsOrders.DataTableDob
riLookup.ValueMember = "ID"
riLookup.DisplayMember = "TITLE"
riLookup.BestFitMode = DevExpress.XtraEditors.Controls.BestFitMode.BestFitResizePopup
GridView1.Columns("Code").ColumnEdit = riLookup`
Here is the photo of that what I am talking about:
I'm wondering how can I handle this repositoryitemlookupedit so if whatever is choosen there I might change value of another column from N to D as I highlighted in a image.
Maybe I can write condition in my appereance-> format condition section.
Whatever I need to change another columns value if something is choosen from this repositoryitemlookupedit, whatever I'm really struggling with this because I've never used before v.b neither devexpress.
Thanks guys
Cheers!
AFTER ALEX HELP:
I put a breakpoint there to check what is e.NewValue and I saw it is acctually ID from database, because I choosed MCI which has ID 1000097 and when breakpoing hitted I catch that Id but with suffix :"D" at the end.. why is that?
You could handle the RepositoryItemLookupEdit.EditValueChanging event.
Just add an event handler to your existing code:
Dim riLookup As New RepositoryItemLookUpEdit()
riLookup.NullText = String.Empty
DataTableDobTableAdapter.FillDob(Me.DsOrders.DataTableDob)
riLookup.DataSource = Me.DsOrders.DataTableDob
riLookup.ValueMember = "ID"
riLookup.DisplayMember = "TITLE"
riLookup.BestFitMode = DevExpress.XtraEditors.Controls.BestFitMode.BestFitResizePopup
GridView1.Columns("Code").ColumnEdit = riLookup
'Add this line:
AddHandler riLookup.EditValueChanging, AddressOf repItem_EditValueChanging
Now just handle the event and do your logic to set the "N/D" column:
Private Sub repItem_EditValueChanging(sender As Object, e As ChangingEventArgs)
If e.NewValue > -1 Then 'any ID given => "N"
GridView1.SetRowCellValue(GridView1.FocusedRowHandle, GridView1.Columns(6), "D")
Else
GridView1.SetRowCellValue(GridView1.FocusedRowHandle, GridView1.Columns(6), "N")
End If
End Sub
(I assumed column 6 from your screenshot).
P.S.: One thing that I couldnĀ“t find in your code but which is neccessary to get a repository item to work properly is to add it to your GridView RepositoryItems collection like:
GridControl1.RepositoryItems.Add(riLookup)

Dataset to set default SelectedValue in DatagridViewComboboxColumn rows

I have a DataGridView (dgwList), into which I load set of items. It's an intermediate form, where user needs to select Action and Category, for which I created DataGridViewComboBoxColumns and set them in Form_Load event like this:
dtCats = ds.Tables(0) ' Datatable with Categories
dtActions = ds.Tables(1) ' Datatable with Actions
Dim colCat As DataGridViewComboBoxColumn = Me.dgwList.Columns("Category")
Dim colActions As DataGridViewComboBoxColumn = Me.dgwList.Columns("Action")
colCat.ValueMember = "ID"
colCat.DisplayMember = "CategoryText"
colCat.DataSource = dtCats
colCat.DataPropertyName = "Category"
colActions.ValueMember = "ID"
colActions.DisplayMember = "Action"
colActions.DataSource = dtActions
colActions.DataPropertyName = "Action"
Everything works fine, when I load items (using another dataset) without default values of Action and Category, I can select them from the DropDownList. However, when I load the second dataset (ds) and use i.e. "Action" to load a value as a default SelectedValue like this:
Dim cmdtext As String = "SELECT ****, 2 as Action, *** WHERE ****; "
Dim ds As DataSet
ds = DAL.GetQueryResults(cmdtext) ' using own Data Access Layer to get dataSet
Me.dgwList.AutoGenerateColumns = False
Me.dgwList.DataSource = ds.Tables(0) ' load the data table
I get "Datagridviewcomboboxcell Value Is Not Valid" error. It seems, that it tries to load it as DisplayMember, or simply a Text property of the DatGridViewComboBoxCell, as it appears as selected text.
I spend a lot of time browsing forums and I found nothing related to dataset (except Set selectedValue in DataGridViewComboBoxColumn where was missing DataPropertyName). Everything is about loops and events raised by user over the comboboxcell.
I would like to avoid the error and use the dataset (not looping to modify each cell) to fill the default values of comboboxes. Any idea?
Ok,
the Devil is in the detail. I had ID set to tinyint data type in the database, while when I was trying to set i.e. 2, it was handled as int32.
I forced input value to int16 and set ID to smallint in DB and then it works - I can set a value:
Dim CBox As DataGridViewComboBoxCell = CType(Me.dgwList.Rows(2).Cells("Category"), DataGridViewComboBoxCell)
CBox.Value = CType(2, System.Int16) ' set value to 2
So I found the problem, but it wouldn't qualify for an answer to my question, because it handles a particular cell, not the dataset. But adding CAST(.... as smallint) to SQL query fully resolves the issue (in combination with setting ID in database to smallint too):
SELECT ...
CAST(CASE COL.Reason WHEN 'Service Fault' THEN 2 WHEN 'Program Fault' THEN 9 END as smallint) as Category
WHERE ... ORDER BY ....;

Devexpress lookup edit select one fill in rest lookups

I'm working on program which uses xpo collection to get and update data from and to database. I setted up lookupedit to get data from another database(country name) I would like another lookupedit (country code) to be filled in automatically after country name is selected.
Here is XPO collection:
Private Countries As New XPCollection(Of clCountry)(UOW)
and here is lookup code:
CountriesLookupRepo.DataSourceConnect("Name", "Name", Countries)
CountryCodeLookUp.DataSourceConnect("ISO2", "ISO2", Countries)
How can I link them up so that ISO2 will be filled automatically after Name is selected?
Thanks
Figured out how to do it.
In case someone else is wondering, this is how I did it :
Dim Country As clCountry = CountriesLookupRepo.GetDataSourceRowByKeyValue(e.Value)
Apt.CountryCode = Country.ISO2
Apt.RegionName = Country.Region
I suggest you to go through this DevExpress thread which describes most of cases to implement this functionality.
How to filter a second LookUp column based on a first LookUp column's value
GridControl, TreeList, and VGridControl provide a special event that
is raised when a cell editor is activated: ShownEditor. This is the
best moment to replace the LookUp editor's data source with the
collection filtered by an appropriate criterion.
example:
Private Sub gridView1_ShownEditor(ByVal sender As Object, ByVal e As EventArgs)
Dim view As ColumnView = DirectCast(sender, ColumnView)
If view.FocusedColumn.FieldName = "CityCode" AndAlso TypeOf view.ActiveEditor Is LookUpEdit Then
Dim edit As LookUpEdit = CType(view.ActiveEditor, LookUpEdit)
Dim countryCode As String = CStr(view.GetFocusedRowCellValue("CountryCode"))
edit.Properties.DataSource = GetFilteredCities(countryCode)
End If
End Sub
and for more information related to your quest of binding XPO objects with LookupEdit check this KB example:
How to: Bind an XPCollection to a LookUp
example:
XPCollection xpCollectionPerson = new XPCollection(typeof(Person));
xpCollectionPerson.DisplayableProperties = "Name;Group!Key";
gridControl1.DataSource = xpCollectionPerson;
XPCollection xpCollectionGroup = new XPCollection(typeof(PersonGroup));
RepositoryItemLookUpEdit lookUpRI = new RepositoryItemLookUpEdit();
lookUpRI.DataSource = xpCollectionGroup;
lookUpRI.DisplayMember = "GroupName";
lookUpRI.ValueMember = "Oid";
gridControl1.RepositoryItems.Add(lookUpRI);
// Associate the LookUpEdit editor with the "Group!Key" column.
(gridControl1.MainView as ColumnView).Columns["Group!Key"].ColumnEdit = lookUpRI;
Hope this help.

How to set a custom DataGridViewColumn for an autogenerated column?

I've downloaded some code relative to establishing a column on my
DataGridView which allows me to use the DateTimePicker.
So far so good. If I add a column using Dim col as new CalendarColumn the grid works great.
However...I need to assign an existing column ...
from a database. How do I make datagridview1.columns("NoteDate") my
CalendarColumn?
Also I tried the following codes
Dim col As New CalendarColumn()
col.DataPropertyName = "NoteDate"
col.HeaderText = "Headertext"
Dim loc As Integer =
dataGridView1.Columns.IndexOf(dataGridView1.Columns("NoteDate"))
dataGridView1.Columns.RemoveAt(loc)
dataGridView1.Columns.Insert(loc, col)
I thought it solve my problems but it only work once if I refresehed my datagrid the NoteDate is populated with values from the database but I cannot make the calendar column working again
Any suggestions?
When you say "an existing column from a database", I guess you mean than you have AutoGenerateColumns property of DataGridView set to True. In this case, you can use the ColumnAdded event and define the CellTemplate for the column.
The example above supposes that your custom DataGridViewTextBoxCell class is named "CalendarCell".
Private Sub dataGridView1_ColumnAdded(sender As Object, e As DataGridViewColumnEventArgs) Handles dataGridView1.ColumnAdded
If e.Column.DataPropertyName = "NoteDate" Then ' for your specific column
e.Column.CellTemplate = New CalendarCell()
End If
End Sub

Unable to set valuemember/display member to bind combobox

I'm having trouble adding dynamically a combo box column to my datagridview (before you ask, yes it must be dynamic and not done in editor).
The main feature is that the combobox cell is different for each row, so it must be done using combo box cell. checkedRows is a datatable.
Name of the datagridview is editCameraTable. It already has a few columns at this point:
'create new column
Dim resComboColumn As New DataGridViewComboBoxColumn _
With {.HeaderText = "Resolution", .ReadOnly = False, .DisplayIndex = 7, .Name = "Resolution", _
.DisplayMember = "Name", .ValueMember = "ID", .DataPropertyName = "ID"}
'add combo box column
EditCameras.editCameraTable.Columns.Insert(17, resComboColumn)
addResCmbBox(checkedRows, resComboColumn)
Pretty straight forward. You'll notice I have the value member, dataproperty name, etc. Here's the addResCmbBox definition:
Public Function addResCmbBox(ByRef DT As DataTable, column As DataGridViewComboBoxColumn)
Dim resolutions As String()
'for each camera
For i As Integer = 0 To DT.Rows.Count - 1
Dim camera As camera = convertDTtoCam(DT, i)
'get the resarray
Select Case DT.Rows(i).Item("Maker").ToString.ToLower
Case "acti"
resolutions = ACTi.GetResArray(camera)
Case Else
resolutions = ACTi.GetResArray(camera)
End Select
'add items to combobox list
Dim comboCell As New DataGridViewComboBoxCell
comboCell.DataSource = resolutions
For j As Integer = 0 To resolutions.Length - 1
'set to current resolution value
If resolutions(j).TrimStart("N") = camera.res Then
comboCell.Value = resolutions(j)
End If
Next
comboCell.DisplayMember = "Name"
comboCell.ValueMember = "ID"
EditCameras.editCameraTable("Resolution", i) = comboCell
Next
Return Nothing
End Function
camera is a structure. I have no problems until I get to the displayMember and value member problem, i.e. the last line starting with "editcameras.editcameratable...".
When doing so, the exception of "The Field Name does not exist" pops up. If I don't assign the displayMember and valueMember, I have no problems. But, I can't get the value selected in the comboBox (it comes back as Null). At runtime, the combobox column has the valuemember and display name as "ID" and "Name".
How can I bind this comboboxcell to the row so that I can later get it's selected value?
UPDATE:
I did as was commented, and created a struct/class that was meant to be the resolution property:
Public Class ResolutionStruct
Property Name As String
Property ID As String
End Class
And within the loop I create a list of this class, and assign the values to it:
Dim resolutionList As New List(Of ACTi.ResolutionStruct)
For j As Integer = 0 To resolutions.Length - 1
Dim resClass As New ACTi.ResolutionStruct
resClass.Name = resolutions(j)
resClass.ID = resolutions(j)
resolutionList.Add(resClass)
Next
'set combocell values
comboCell.DisplayMember = "Name"
comboCell.ValueMember = "ID"
comboCell.DataSource = resolutionList
EditCameras.editCameraTable("Resolution", i) = comboCell
However, the comboboxCell doesn't show any value when it drops down. So, now I've bound the values but it shows nothing. Is there anything else I should be doing so that I get both the holy combo of seeing the values I'm picking AND having them be bound to the data grid view? :D
UPDATE 2
So, mea culpa. I was adding the combobox cell to the wrong column!
So now, it is showing the values. I click a value, and try to grab the selected value as as string:
Dim cmbbox2 As DataGridViewComboBoxCell = editCameraTable("Resolution", i)
resolution(i) = cmbbox2.Selected.ToString()
But it still says it's a null value! Mid build I checked the combobox props. IN fact "selected" is a boolean as false. It has no value, says it has no items as well. Any ideas on why it says it is null?
UPDATE3:
I recently resorted a different column in the table, and the values from the combo box are cleared! I guess it's really never being attached/bound in the first place.
UPDATE4:
Fixed it!!
Apparently this line:
editCameraTable.Sort(editCameraTable.Columns("ID"), System.ComponentModel.ListSortDirection.Ascending)
Caused the table to freak out! I can now get the value (woohoo!)
Right, I'll try to explain this shortly:
DisplayMember and ValueMember are supposed to be set using properties. For example you create a class containing Name and ID
Public Class Test
Property Name as String
Property ID as String
End Class
Create a few of these objects and put them in a list. Set the list as the datasource to the combobox. Now you can access the DisplayMember and ValueMember as you have written it in your code. Value would be the ID and SelectedItem would be the entire class.
What you are doing now is that you are adding a list of strings to the combobox. A String does not contain the Property Name nor ID, so naturally you can't fetch them. See it like this:
To be able to use Value and/or DisplayMember you need to be able to fetch the Property by yourself. In this case:
resolutions(j).Name
or
resolutions(j).ID
This does not work.
But for example you would be able to do this:
resolutions(j).Length
So You would be able to do this, which would display the Length in the combobox:
Combobox.DisplayMember = "Length"
To currently get the value you would have to do:
Combobox.SelectedItem.ToString()
But since you have it in a combobox column My guess is that this won't cut it since you can't fetch the value from the DataGridView.
EDIT: You are still doing this right?
<DataGridView>.Item("Resolution", i) = comboCell
Otherwise you will have empty comboboxes.
EDIT2: No need to fetch value from Combobox, get it from Grid cell instead:
<DataGridView>.Item("Resolution", i).Value
When creating the columns don't forget to set a defaultvalue to the combobox, otherwise it might be Nothing:
comboCell.DisplayMember = "Name"
comboCell.ValueMember = "ID"
comboCell.Value = resolutions(0)