Looping through Comboboxes on form and clearing datasource - combobox

I'm having some trouble looping through the comboboxes on my form and to clear the data sources (using VB.net in Visual Studio 2017)
the code I have so far is this:
==============================
For Each c As Control In Me.Controls.OfType(Of ComboBox)()
If c.Name IsNot Control.Name Then c.datasource = Nothing
Next
==============================
However, get the error " 'DataSource' is not a member of 'control' "
The "Control" is a variable passed to the sub
====================
Public Sub Item_Select(ByRef Field As String, ByRef Control As Control)
====================
and is called like this
==================
Dim Control1 As Control = ComboBox2
Item_Select("Last_Name", Control1)
==================
The datasource is an SQL table
Could anyone point me in the right direction? I don't seem to be getting the right search terms in google for a workable solution!
Thanks so much in advance, and apologies if this post is inappropriate (i have read the guide!)

This woks as a solution!
For Each c As Control In Me.Controls
If TypeOf c Is ComboBox Then
Dim ctrl = DirectCast(c, ComboBox)
ctrl.DataSource = Nothing
End If
Next

Related

WPF DataGrid Double-Click Exception

Long-time WinForms programmer relatively new to WPF. I'm databinding a DataGrid in Code-Behind using a SQL Query. I reuse the DataGrid because I'm using Ribbon Tabs and reload different data in the grid dependent on the Tab selected. So binding to a static resource is not possible.
I'm trying to open a new window on a double-click event but get the following exceeption - "Unable to cast object of type 'System.Windows.RoutedEventArgs' to type 'System.Windows.Input.MouseButtonEventArgs'."
This used to be a simple thing in WinForms. My code is as follows:
Try
Dim StrRow As DataRowView = MainDataGrid.SelectedItem
Dim CellValue As String = StrRow.Row(0).ToString()
'MsgBox(CellValue)
e.Handled = True
Dim EventDetails = New EventDetails()
EventDetails.Show()
OpenEventDetailsWindow()
Catch ex As Exception
MsgBox("No Event No.for this Event")
End Try
The messagebox shows the proper string (first cell value of selected row and the new window actually pops up right before the exception is thrown. I've seen plenty of posts that say this method should work but it doesn't. I've been so far unsuccessful in fixing this. Thanks in advance.

VB.NET Need guide on error checking using MessageBox

Lets say I have a form with 100 textboxes, comboboxes and other controls and I want to check if any of the controls is empty. When I click on 'OK' button, I want the messagebox to show a list of errors example Textbox1 is empty, Textbox30 is empty and such.
I can achieve this by doing the tedious method where I check textbox1 and messagebox is shown, check textbox2 and messagebox is shown again and so on.
I want the messagebox to show only once. How can I achieve this?
What I have did is that I set up an array and store all the error messages to be shown later by selecting (example Msgbox(errMessages(3) + Environment.newline + errMessages(30)) and I know this is not the right way to do it as well.
Please and thank you in advance.
Here is a direct answer to your question:
You can store the empty controls in a list, and at the end create the message like this:
Dim empty_controls = New List(Of Control)
If TextBox1.Text = String.Empty Then
empty_controls.Add(TextBox1)
End If
If TextBox2.Text = String.Empty Then
empty_controls.Add(TextBox2)
End If
Dim result As String = String.Join(
Environment.NewLine,
empty_controls.Select(Function(c As Control) c.Name + " is empty"))
MessageBox.Show(result)
Here is even a better way to detect which text boxes are empty:
Dim empty_controls = New List(Of Control)
//The following line will search through all text boxes on the form
empty_controls.AddRange(
Controls.OfType(Of TextBox).Where(Function(c As Control) c.Text = String.Empty))
//Here you can add other kinds of controls with their own way of determining if they are empty
Dim result As String = String.Join(
Environment.NewLine,
empty_controls.Select(Function(c As Control) c.Name + " is empty"))
MessageBox.Show(result)

WPF SelectionChange Event for ComboBox with Binding from database crashes the Program

I've got a big issue trying to modify the ItemSource for a ComboBox. When I try to debug the app by putting a breakpoint on MessageBox.Show(...) in the Sub cboTest_SelectionChanged (see below), I get this error:
An Unhandled exception of type 'System.InvalidCastException' occured in Data.exe
Additional Information:
Unable to cast object of type 'System.Data.DataRowView' to type 'System.Windows.Controls.ComboBoxItem'
How can I fix this?
Here's what I do. I create an ACCESS 2007 Database named SNIGDoFFE.accdb, my solution is named Data, I added the Database through the Add New Source Configuration wizard and I drag and drop the Field "Libelle" from the Table Ethnie to the the ComboBox, so it modifies my files like this:
In MainWindow.xaml.vb
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles MyBase.Loaded
Dim SNIGDoFFEDataSet As Data.SNIGDoFFEDataSet = CType(Me.FindResource("SNIGDoFFEDataSet"), Data.SNIGDoFFEDataSet)
'Load data into the table Ethnie. You can modify this code as needed.
Dim SNIGDoFFEDataSetEthnieTableAdapter As Data.SNIGDoFFEDataSetTableAdapters.EthnieTableAdapter = New Data.SNIGDoFFEDataSetTableAdapter.EthnieTableAdapter()
SNIGDoFFEDataSetEthnieTableAdapter.Fill(SNIGDoFFEDataSet.Ethnie)
Dim EthnieViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("EthnieViewSource"), System.Windows.Data.CollectionViewSource)
'EthnieViewSource.View.MoveCurrentToFirst
'I comment this line to leave the combobox empty
End Sub
The code for cboTest_SelectionChanged is:
Private Sub cboTesT_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles cboTesT.SelectionChanged
MessageBox.Show(CType(cboTesT.SelectedItem, ComboBoxItem).Content)
End Sub
In XAML:
<ComboBox x:Name="cboTest" width="120" Margin"184,10,183,134" SelectionChanged="cboTest_SelectionChanged" DisplayMemberPath="Libelle" ItemSource="{Binding Source={StaticResource EthnieViewSource}}" />
In my Resources:
<Window.Resources>
<local:SNIGDoFFEDataSet x:Key"SNIGDoFFEDataSet" />
<CollectionViewSource x:Key="EthnieViewSource" Source="{Binding Ethnie, Source={StaticResources SNIGDoFFEDataSet}}" />
</Window.Resources>
The Solution is built correctly, the main Window loaded correctly, but when I select an item in the combobox, the program crashes. I try to remove all binding and create Item with and everything work, but by binding the source from my database, it crashes again.
The program crashes because you allow the exception to propagate out of your code. To stop the program from crashing, place everything in your SelectedChange event handler in a try catch block.
This should become a standard for all 'windows entry points' into your code. Whether it is an event or a command, if you didn't call it from your code, use a try catch block to stop exceptions from propagating out of your code.
Regarding the error, you are binding data to your ComboBox. When you interrogate the SelectedItem, it will be of the type of the data (in your case, of type System.Data.DataRowView), not a ComboBoxItem.
If you need the containing ComboBoxItem of the selected item, use the ItemContainerGenerator.ContainerFromItem() to find it, for example
Private Sub cboTesT_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles cboTesT.SelectionChanged
Try
Dim combo As ComboBox = CType(sender, ComboBox)
Dim item As ComboBoxItem = combo.ItemContainerGenerator.ContainerFromItem(combo.SelectedItem)
MessageBox.Show(item.Content)
Catch ex As Exception
' Log or display exception.
End Try
End Sub
If you are just after the data, CType the SelectedItem to your datatype (System.Data.DataRowView) and work with it directly.
I hope this helps.
Sorry Mark, to be so long
and again I'm sorry a lot
on msdn forum, they told me that as the binding source is a Table in a database I must use DataRowView instead of ComboBoxItem,
Dim drv As System.Data.DataRowView = CType(cboTest.SelectedItem, DataRowView)
MessageBox.show(drv("Libelle").ToString())
Don't hesitate to help me another time, please.

How to retrieve a particular cell value from a wpf datagrid without selecting the cell or the respective row?

I m working with WPF DataGrid and I want to retrieve a DataGridCell's value by using the column and the row indexes : all what I could do is this but it didn't work :
myDatGrid.Columns[0].GetCellContent((DataGridRow)myDatGrid.Items[0]);
Could you please show me the way to realize that
Your cells value is going to be contingent on what the given column is bound to. The entire row will be the instance of your model.
Assume we have a collection of Person classes which we are binding to within our DataGrid.
Person p = ((ContentPresenter)myDatGrid.Columns[0].GetCellContent(myDatGrid.Items[0])).Content;
The Content property is going to return the underlying model for the row. If you wanted to obtain a given property you can do so by directly accessing the underyling object which should implement INotifyPropertyChanged, no need to fool with the DataGrid as you would in a WinForms application.
I tried what has been proposed above and it did not work.
I struggled for a whole day trying to bind a ComboBox and select the correct value in a WPF Datagrid when it first loads, so I thought I would share my solution here in hopes that somebody else could benefit. Sorry about the VB, but the concept should work in C# also.
First, if you are trying to get the values populated and selected when the grid first loads, you need to put your code in the correct event handler: LayoutUpdated. In other event handlers, the GetCellContent function returns Nothing (null). You could also put this code in an event handler which handles an event occurring later, such as a Button.Click event, if that meets your requirements.
Second, the code:
For i As Int32 = 0 To DataGrid1.Items.Count - 1
Dim row As DataGridRow
row = DataGrid1.ItemContainerGenerator.ContainerFromItem(DataGrid1.Items(i))
If row IsNot Nothing AndAlso row.Item IsNot Nothing Then
Dim cp As ContentPresenter = DataGrid1.Columns(3).GetCellContent(DataGrid1.Items(i))
If cp IsNot Nothing AndAlso cp.ContentTemplate IsNot Nothing Then
Dim dt As DataTemplate = cp.ContentTemplate
If dt IsNot Nothing Then
Dim cb As ComboBox = dt.FindName("cbVendorNames", cp)
If cb IsNot Nothing Then
cb.ItemsSource = Vendors
cb.DisplayMemberPath = "VendorName"
cb.SelectedValuePath = "AS_ID"
cb.SelectedValue = "" ' set your selected value here
End If
End If
End If
End If
Next
What this code does is (a) loop through all of the rows in the datagrid, (b) get the ContentPresenter for the cell selected (in this case, cell 3 in each row), (c) get the DataTemplate for the ContentPresenter, and (d) finally, get the reference to the ComboBox. This allowed me to bind the ComboBox to an external datasource (a List(Of Vendor) and select its value. This code worked for me.
I do not find this solution particularly elegant or efficient, but it does work. If somebody has a better solution, please post it.
OK I think I got it , I missed some casts that I should put , because the column I'm using is a DataGridComboBoxColumn
I should actually do this :
((ComboBox)(myDatGrid.Columns[0].GetCellContent(
(TestData)myDatGrid.Items[0]))).SelectedValue.ToString());
Now it works.

How do I bind a SQL bit field to a True/False combobox or listbox?

I store True/False values as bit fields in SQL Server. The fields are nullable. What is the XAML syntax to bind a bit field to a WPF combo box so the user can choose True/False or blank (null)?
By the way, I'm binding to a strongly-typed dataset/datatable. Drag and drop binding has simplified binding to other datatypes. I certainly don't mind editing the XAML, but I'm wondering if drag and drop can be made to work in this scenario?
Just as a suggestion for anyone else who comes across this issue (without having to do the XAML stuff), I did the following using Linq (VB 2008):
Private Sub BindMyCombo()
Dim yesNo As String() = {"No", "Yes"} 'Or false, true or nay, yay -whatever
Dim bits = From bit In yesNo _
Select New With { _
.BitVal = Cbool(Array.IndexOf(yesNo, bit)), _
.BitText = bit _
}
With Me.myBitComboBox
'Clear anything in the combo first if necessary...
.DataSource = Nothing
.Items.Clear()
'New binding in case there are more "bits" to be used elsewhere in your form
.BindingContext = New BindingContext
.DataSource = bits.ToList
.DisplayMember = "BitText"
.ValueMember = "BitVal"
End With
End Sub
After that it's just a matter of doing the binding with the dataset. When you do, specify that when the bit value is null to set the combos selectedValue to blank or nothing, for example...
With Me.myBitComboBox
.DataBindings.Clear()
.DataBindings.Add(New Binding("SelectedValue", myDataSetName, "myBitFieldName", _
True, DataSourceUpdateMode.OnPropertyChanged, Nothing))
.SelectedValue = IIf(mdDataSetName.myBitFieldName.ToString = "", "", _
myDataSetName.myBitFieldName)
End With
I hope this helps anyone else that comes across this issue (like me).
You will likely need to create a value converter (a class which implements the IValueConverter interface) which can translate the value of a bit field to a boolean value. Part of the problem, out of the box, is that how do you represent a null value as a boolean state? That typically depends on the business process or rules.

Resources