Using list of custom Class object as data source for crystal report - vb.net

I am trying to find way to design a report using my own custom class.
I found links:
1.) How to work in Crystal Report with Object Data Source?
2.) Use .net object as data source in Crystal Report 2008
3.) Binding object with List<> to Crystal Report
4.) How to assign Custom class as datasource in crystal report
They were quite helpful, but I have been stuck in the first step while designing report as my custom class's property is not listed in field list of crystal report design view.
Sample of my Custom Class:
class UserType
public property UIN as integer...
public property Title as string...
end class
class User
public property UIN as Integer...
public property Name as string...
public property Password as String...
public property Type as UserType...
end class
When I add my class objects to crystal report I do not get the usertype field from users class in field list.
So how can I add usertype field to my field list? Or do I have to take another approach?
Edit:
The reason i wanted to use it as i am:
1.) Showing a form where user can type keyword
2.) program filters the records as per keyword using LINQ
3.) when user clicks the print button, I want to set the filtered records as datasource of my report

Create your dataset with the columns matching your class, and assign
the dataset to your report normally.
When you have your object class loaded with data, and/or filtered with values entered by users (filtered with linq etc..)
do this:
dim yourDataset as dataset ' this is your typed dataset
Dim dr As datarow
For n As Integer = 0 To yourClass.Count - 1
dr = yourDataset.tables("TableName").NewRow
dr("ColumnNameOne") = yourClass(n).PropertyName
dr("ColumnNameTwo") = yourClass(n).PropertyName
yourDataset.tables("TableName").Rows.Add(dr)
Next
' bind the datasource
crystalreport.SetDatasource(ds)

You could try serializing the object to XML, supply an XSD, then use Crystal Report's XML driver to connect to it. The report will 'see' the object as two tables: one for the User and one for UserType. You'll include both 'tables' in the report and link the tables using the internal_id field.

Why don't you assign a strongly typed dataset to your report and save yourself lots of trouble?

Related

DataList object has no method DataBind()

I am trying to get the results of a SQL Server stored procedure in VB.NET, parse them into a DataSet, then use the DataSet to fill a Windows Forms ListBox.
I have found many, many tutorials. The only ones that have gotten me close to a solution are ones that depend on the ListBox's DataBind() method. However:
myListBox.DataBind()
' ERROR: 'DataBind' is not a member of 'ListBox'
This is contrary to every tutorial I've found on the topic (approx a dozen so far).
Here is more code context:
Dim connection As New SqlConnection(myConnectionSecret)
Dim command As New SqlCommand("myStoredProcedureName")
command.Parameters().Add("#myParam", SqlDbType.Int).Value = myParamValue
command.Connection = connection
command.CommandType = CommandType.StoredProcedure
Dim adapter As New SqlDataAdapter(command)
adapter.SelectCommand.CommandTimeout = 300
'Fill the dataset
Dim dataSet As New DataSet
adapter.Fill(dataSet)
connection.Close()
myListBox.DataSource = dataSet
myListBox.DataBind() ' This method not found
A dataset is a collection of datatables. Typically you would bind your listbox to only one datatable. You can set the DataSource property to a dataset but you'll then also need to set the DataMember property to the name of the table in the dataset so the binding knows which table to rummage in
myListBox.DataSource = dataSet
myListBox.DataMember = "Person" 'whatever your table name is
Or set it to refer to the table directly:
myListBox.DataSource = dataSet.Tables("Person")
As other answers have commented you should then set the DisplayMember (chooses what text appears in the control) and ValueMember (chooses what value is emitted by the listbox.SelectedValue property) properties to strings representing the column names. If I want to show my persons name in the list but have their email be the selected value:
myListBox.DisplayMember = "FullName" 'fullname is a column in the datatable
myListBox.ValueMember = "Email"
If you don't set a ValueMember the whole DataRow of the selected person is returned from SelectedValue. (Clarification: Actually, it's a DataRowView because binding to a datatable actually happens to a DataView exported by the .DefaultView property - more on this later)
So, we've bound our list.DataSource to a datatable, and set the diplay/valuemember properties. How to we get the details of what Person is selected currently? Put a button on the form that has this handler code:
MessageBox.Show(DirectCast(listbox.SelectedValue, string)) 'shows e.g. john.smith#hotmail.com
Run the program, click "John Smith" in the list then click the button. The messagebox will show the selected person's email address
I mentioned earlier that databinding happens to a DataView object exported by the table's .DefaultView property. A DataView is a collection of DataRowView objects, and a DataRowView is a thin wrapper around a DataRow. DataRows exist in various versions such as original or updated values. A DataRowView is a way of selecting one of these versions for presentation, by default the Current version. You can address it like you would a DataRow:
'accessing the email address of a datatable row
Dim myDataRow = myPersonTable.Rows(0)
Dim email as String = DirectCast(myDataRow("EmailAddress"), string)
'accessing the email address of the dataview exported by the table defaultview
Dim myDataRowView = myPersonTable.DefaultView(0)
Dim email as String = DirectCast(myDataRowView("EmailAddress"), string)
As you can see, there isn't a lot of difference - as noted, the view just shows one of the various versions a datarow can exist in. If you want to get access to the underlying row you can do it via the Row property:
Dim myDataRowView = myPersonTable.DefaultView(0) 'or however you ended up holding a DataRowView object
Dim dr as DataRow = myDataRowView.Row
If you're using strongly typed datatables (discussed below), and want the strongly typed row:
Dim dr as PersonDataRow = DirectCast(myDataRowView.Row, PersonDataRow)
A useful aspect of the list binding to the .DefaultView DataView is that it can have its own filtering and sorting setup:
Dim dv = dataSet.Tables("Person").DefaultView
dv.Sort = "[FullName] ASC"
dv.RowFilter = "[FullName] LIKE 'J*'"
For more info on these see the documentation for dataview
Now, sea change: you don't have to do any of this by hand. All this can be linked up and done by visual studio and there are compelling reasons for doing so. For the same reason you don't write your form codes by hand, manually laying out all your controls etc, you can visually design and maintain your data access layer
Add a new dataSet file to your project, open it, right click the design surface and choose to add a tableadapter, go through the wizard setting your connection string and choosing that it's a stored procedure that gives you the data. At the end of it you'll see a datatable representation and all the columns returned by your stored procedure
If you now show the data sources window when you're in your forms designer you'll see a node representing your table from your dataSet, and you can either drag that node onto the form to create a DataGridview that is hooked up leafy, or you can expand the node in the data sources window to see individual columns, you can change the type of control to create for that property and you can drop them on the form. (I can't remember if listbox is one of them, but I know that ComboBox is). Dropping them on the form simply creates a control, already named and wired up with the right DataSource, Member and DisplayMember properties set, and you can change these and other properties like the value member in the properties grid.
Most critically of a difference, the controls the designer creates are all bound through a device called a bindingsource - this tracks the row in the datatable you're currently looking at, and keeps data bound controls in sync. If one control such as a grid or list is capable of showing multiple rows, clicking on different rows changes the Current property of the binding source, causing other controls (that only render one data row's data) such as textboxes to update to the new Current row values
Thus list controls may operate in one or two modes: they either serve as a device that can navigate a datatable's rows allowing you to pick one of a few rows so that you can edit the values using other textboxes etc, or lists serve as a way of showing a set of values for the user to cope from and cause another datarow's property to update to that chosen value. The differentiation in these two modes comes from whether the selectedvalue property is bound to something else or not. As a simple example in the context I've been discussing already, we could have a dataSet with two tables; person and gender; the person table has a gender column single char M or F, and the gender table has two columns one is a single char M or F and the other a text column of Male or Female (I won't get into the cases for other genders right now but the system is easy to extend by adding more rows). You could then have a form where the person table plus its binding source is causing a list of people to show in the first list box and click in different items in the list causes all the other textboxes (FullName) on the form to change so you can edit those details. You can also have a second listbox bound to the gender table via its own bindingsource (or direct, doesn't matter) that has its DisplayMember set to the "Male/female" column, its value member set to the "m/f" column and it's SelectedValue property bound to the main Person bindingsource's Person.gender column. When you choose a person from the first list, the current char value of their Gender will be used to set the current item selected in the gender list but if you change the value in the gender combo/list then it will write the new selectedvalue back into the person.gender column
That's the 101 of Windows forms binding; I recommend adding a dataset to your project because it then gives you datatables that are specifically typed with named properties. Your code looks like this:
ForEach PersonDataRow r in myDataset.Person
r.Age += 1
Instead of this:
ForEach DataRow r in myDataset.Tables("Person").Rows
r("Age") = DirectCast(r("Age"), Integer) +1
I was mid-answer when jmcilhinney commented: DataBind() is specific to ASP.Net Web Forms server controls.
Therefore, the DataBind() call isn't necessary, simply setting the DataSource property on a Windows Forms ListBox is enough.
As for parsing your results from your SQL Server, don't forget to set the ListBox's DisplayMember and ValueMember properties to correctly display your data to the user.
Here's the documentation on the DataSource property. It has a very decent example.
For filling a list box, you usually don't need DataSets or DataAdapters. Just a DataTable table will do.
The Using...End Using blocks ensure that your database objects are closed and disposed.
You can pass the connection directly to the constructor of the command.
Set the list box data source to the DataTable. Then you can use the names of the fields in the Select statement to set the .DisplayMember and .ValueMember. The display and value can be the same.
Private Sub FillListBox(myParamValue As Integer)
Dim dt As New DataTable
Using connection As New SqlConnection("myConnectionSecret")
'Pretend your stored procedure has a statement like "Select DeptarmentID, DepartmentName From Departments Where SupervisorID = #myParam;"
Using command As New SqlCommand("myStoredProcedureName", connection)
command.CommandType = CommandType.StoredProcedure
command.Parameters().Add("#myParam", SqlDbType.Int).Value = myParamValue
connection.Open()
dt.Load(command.ExecuteReader)
End Using
End Using 'Closes and disposes the connection
ListBox1.DataSource = dt
ListBox1.DisplayMember = "DepartmentName"
ListBox1.ValueMember = "DepartmentID"
End Sub

How to get the value of a control that's bound to a binding source in VB?

I have a Dialog which has a ComboBox (aComboBox, say) with the following properties set:
DataSource linked to a BindingSource which is linked to an SQL table
DisplayMember linked to a column in that table which is of type String
Here is a pic of how the properties are set:
I want the String value of the item selected in the combo box but I am getting System.Data.DataRowViewwhen I use this code at run time:
aComboBox.SelectedItem.ToString()
How do I get the String value?
Do not use aComboBox.SelectedItem.ToString()
Instead of that Use : aComboBox.SelectedValue()
I managed to fix this by setting the Value Member attribute as shown in the following image, I am then able to retrieve the String value by calling aComboBox.SelectedValue.ToString() :
Note: Before, I only had the Display Member attribute set.

How to Access DataTable Information Filled By a Module From a Form

I have a DataSet named BillMat.xsd
When my application loads, a module fills that dataset's DataTable with the correct information.
My question is ... How can I access that DataTable's already filled information from another form?
Here's how I tried to access it on one of my forms:
Dim View As New DataView
View.Table = BillMat.Tables("dtBillHeader")
But I get the following error:
If I create a new instance of my dataset and store it in a variable, I'll be able to get rid of this error message but it will also get rid of all my data in my dataset's datatables ... Is there a way to access a DataTable's information from another form?
You need to fix it so both forms are referencing the same DataSet or DataTable object. If one is a "child" form of the other, such as a dialog, you can pass it from the parent to the child via a property. Otherwise, ideally, the same data object would be injected into both forms by some third object which created both of the forms. Short of all that, you could create a singleton or global variable, but please don't!

DataList Control in vb.net windows application forms

I am upgrading my application from vb6 to vb.net.
I used to populate my data in datalist control in vb6 forms. I am not finding it in vb.net windows form application. Which one control is the equivalent to it?
How can i list my data in that control?
just like:
I had a table with data like id, name
I want the name should be the displayed column and id the bound column? how can i do that
I'm not exactly sure but I think you're looking for a ListBox. You create a class with 2 members and a property for each (suggested property names ID and Name), create a list of them and put all your data in there and then just set the 'ListBox.DisplayMember' to "Name" and ListBox.ValueMember to "ID".
The MSDN page for ListControl.DisplayMember has a full sample showing how to do it as can be seen here.
Though I'd suggest that you use a List(Of YourClass) rather than the ArrayList in the sample.

How can I use strongly typed lists as the datasoruce for a Crystal Reports

I currently have
Class A
property x as List (Of Class B)
End Class
Class B
' some other properties
End Class
When I create crystal report to use Class A as datasource the field explorer doe snot show property x?
Is it possible to use strongly typed lists with Crystal Report?
I'm not 100% sure about List, but you can use ArrayList instead. See my answer on this question:
How to use Crystal Reports without a tightly-linked DB connection?