Devexpress lookup edit select one fill in rest lookups - vb.net

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.

Related

DataGridView Column Header Cell Drop-Down Filter List, make case insensitive

As per this item I have added code to a datagridview to automatically add column filtering list to certain column headers.
Private Sub DataGridView1_BindingContextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DataGridView1.BindingContextChanged
For Each col As DataGridViewColumn In DataGridView1.Columns
If col.Name = "rating" Or col.Name = "check" Or col.Name = "artist" Or col.Name = "genre" Or col.Name = "album" Or col.Name = "year" Or col.Name = "bpm" Or col.Name = "cover" Then
col.HeaderCell = New DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell)
End If
Next
End Sub
Private Sub DataGridView1_DataBindingComplete(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
FilterText = DataGridViewAutoFilterColumnHeaderCell.GetFilterStatus(DataGridView1)
If String.IsNullOrEmpty(FilterText) Then FilterText = ""
End Sub
However if my database bound column data contains the same string but with different cases the filter list contains multiple entries. For example my data for the datagridview artist column might contain "Abba" and "ABBA" and the datagridview auto generated column header list contains both case versions.
How can I make the list case insensitive without modifying the underlying database data case so I only see "Abba" once in the list. (note I do not create the list as it is generated automatically from the bound datagridview database source data, see the link above)
Although the code provided by Jimi did not resolve the issue it did give me a hint as to where to look.
I needed to expose PopulateFilters() to get to the code where I could manipulate the data being created for the Datagridview column header filter lists. To do this I downloaded the example given in the link above.
From this I added DataGridViewAutoFilter.dll to my project and added the reference "Imports DataGridViewAutoFilter". This allowed me to open the public class DataGridViewAutoFilterColumnHeaderCell which contained the PopulateFilters() sub.
To prevent case duplicates being created in the list I simply created a List Of String
Dim valueitems As New List(Of String)
For Each value As Object In list
If Not valueitems.Contains(value.ToString.ToLower) Then
valueitems.Add(value.ToString.ToLower)
'original PopulateFilters code...
End If
Next value
Obviously there are other methods I could have used to get rid of duplicates however this worked for me.

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)

DGV combobox displays, but does not choose, default value

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.

Sorting value in the combobox without losing the indexes which are associated

In my app I make a code that get content from web page.
The team name that was get from web, is order in combobox in sequentially mode, that's as they are read.
I store the value read in Classifica_Table, so I execute this code for adding the value:
For Each Team As Team_Data In Classifica_Table
ComboBox1.Items.Add(Team.Name) 'Populate Combo Boxes with team names
Next
Now I own something like Juventus, Roma, Inter that are messy and not in order of alphabet.
I tried to order them in the past with something like:
For Each Team As Team_Data In Classifica_Table.OrderBy(Function(x) x.Name)
ComboBox1.Items.Add(Team.Name)
Next
This worked only for the look and feel, because the indexes within the table are lost.
For example if I have associated:
Juventus => 3
Rome => 5
Inter => 2
I find myself into:
Inter => 3
Juventus => 5
Rome => 2
as it should be:
Inter => 2
Juventus => 3
Rome => 5
Would there be a way to sort the values without losing the indexes they are associated?
More details:
Dim Classifica_Table() As Team_Data
The index of each team is associated with this:
Classifica_Table(ComboBox1.SelectedIndex).Partite_Giocate
and .Partite_Giocate is a variable that is enhanced during the download of the data.
Complete structure of the code:
1. Adding data download in the combobox:
Classifica_Table = Fill_Table(Classifica_JS)
ComboBox1.Items.Clear()
For Each Team As Team_Data In Classifica_Table
ComboBox1.Items.Add(Team.Name) 'Populate Combo Boxes with team names
Next
2. Fill table valorize the variable of each "teams", so i've this variable valorized with data from internet:
.Partite_Giocate..
.Vincite..
.Pareggi...
.Perdite...
.Goal_Segnati..
.Goal_Subiti...
This is a integer variable
3. Index of each teams in combobox:
Classifica_Table(ComboBox1.SelectedIndex).Partite_Giocate
And so on.. that's it.
SelectedIndex is a property that keep track of the position of the item selected in the combobox items, it is not to be used as an index in another collection.
If you want to keep a value associated with your displayed item (Name) then the approach to add items to your combo should be substituted with a DataBinding approach;
Dim bs = new BindingSource()
bs.DataSource = Classifica_Table.OrderBy (Function(x) x.Name)
ComboBox1.DataSource = bs
ComboBox1.DisplayMember = "Name"
ComboBox1.ValueMember = "Partite_Giocate"
Remember that this method now requires a reevaluation of every point where you read values back from the combobox. Now your ComboBox Items are instances of a Team class and you get them back using the SelectedItem property with a DirectCast to Team. To get the Value of an Item you read the SelectedValue property and so on...
So for example, if you want to track the combobox change event you could write
Sub comboBox_SelectedIndexChanged(sender as Object, e as EventArgs)
Dim b = DirectCast(sender, ComboBox)
if b.SelectedItem IsNot Nothing Then
Dim t = DirectCast(b.SelectedItem, Team)
Console.WriteLine("Partite Giocate=" & t.Partite_Giocate)
End If
End Sub
EDIT
Looking at your project, this is an example on how I would change your code in the SelectedIndexChanged of the ComboBox1. In that method you use the SelectedIndex values as an index to the Classifica_Table array of structure. This is wrong of course you want to rearrange the display of the Teams in your combo. Instead, you should try to find the current selected Team_Data value using the Name because this is an unique value in your combo.
Private Sub ComboBox1_SelectedIndexChanged(.....) Handles ComboBox1.SelectedIndexChanged
If ComboBox1.SelectedIndex = ComboBox2.SelectedIndex Then
MsgBox(".....")
Exit Sub
End If
' Get the Team_Data corresponding to the Text currently selected
Dim td = Classifica_Table.Where(Function(x) x.Name = ComboBox1.Text).SingleOrDefault()
Dim Shield As Bitmap = Bitmap.FromStream(New MemoryStream(New WebClient().DownloadData(td.Shield)))
Shield_1.Image = Shield
Rating_1_1.Value = td.Partite_Giocate
Rating_1_2.Value = td.Vincite
Rating_1_3.Value = td.Pareggi
Rating_1_4.Value = td.Perdite
Rating_1_5.Value = td.Goal_Segnati
Rating_1_6.Value = td.Goal_Subiti
.....
Of course with this approach you don't need to use the DataBinding feature and you could sort your Teams because the retrieve of the Team_Data to use no more use the SelectedIndex property
One way to do it:
First insert all teams so you have a list with all teams
For Each Team As Team_Data In Classifica_Table
ComboBox1.Items.Add(Team.Name)
Next
Then replace them at correct position in list:
For Each Team As Team_Data In Classifica_Table
ComboBox1.Items.RemoveAt(Team.Index)
ComboBox1.Items.Insert(Team.Index, Team.Name)
Next

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