Databinding list of objects to a data grid view - vb.net

I have this manual adding of data or row in the grid and I would like to ask some idea on how to implement data binding in vb.net.
memberGrid.Rows.Clear()
For Each m As Member In members
Dim row As Object() = {m.MemberId, EntityHelper.FullName(m.Person.FirstName, m.Person.SurName),
WorkoutLogic.GetLastWorkoutDateDisplay(m.MemberId, AppRuntime.Workouts),
LogicService.GetMembershipStatus(m.MembershipHistories),
m.Person.Mobile}
memberGrid.Rows.Add(row)
Next

Try something like
memberGrid.DataSource = (From m In members
Select New With { Id = m.MemberId,
FullName = EntityHelper.FullName(m.Person.FirstName, m.Person.SurName),
LastWorkout = WorkoutLogic.GetLastWorkoutDateDisplay(m.MemberId, AppRuntime.Workouts),
Status = LogicService.GetMembershipStatus(m.MembershipHistories),
Mobile = m.Person.Mobile }).ToList()
Change the names before the ='s to match the names of your columns.

Related

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.

Aviod duplicate items in datasource bind checked list box in vb

I made program for populating the data in checked list box. But the problem is the repeated names are displayed in checkedlist box. My code is given below. How can I avoid the duplicate names in checkelstbox using this databind property?
Dim str = "select distinct t.vc_doctype ***********"
conobj.readdata1(str)
CheckedListBox1.DataSource = conobj.ds.Tables(0)
CheckedListBox1.DisplayMember = "vc_doctype"
CheckedListBox1.ValueMember = "vc_doctype"
If you dont want to check your query, you can get whatever result to a datatable and in your code you can get the distinct values to a new Datatable.
For the code above you can follow something like this
Dim view As New DataView(conobj.ds.Tables(0))
Dim DistinctValues As New DataTable
DistinctValues = view.ToTable(True, "vc_doctype")
CheckedListBox1.DataSource = DistinctValues
CheckedListBox1.DisplayMember = "vc_doctype"
CheckedListBox1.ValueMember = "vc_doctype"

Select By Key Values from a LINQ Query in a view

I am trying to grab each key value from a LINQ Query and pull them into my view. The LINQ query looks like this:
Public Property ByVDN As IEnumerable
Get
Dim valQ = (From scr In Var.db.CareSideA.ScriptCrossReferences
Join s In Var.db.CareSideA.Scripts On s.ScriptID Equals scr.ScriptID
Join ms In Var.db.CareSideA.MasterScripts On s.MasterScriptID Equals ms.MasterScriptID
Join svce In Var.db.CareSideA.Services On svce.SkillTargetID Equals scr.ForeignKey
Join p In Var.db.CareSideA.Peripherals On svce.PeripheralID Equals p.PeripheralID
Join sm In Var.db.CareSideA.ServiceMembers On svce.SkillTargetID Equals sm.ServiceSkillTargetID
Join sg In Var.db.CareSideA.SkillGroups On sm.SkillGroupSkillTargetID Equals sg.SkillTargetID
Where s.Version = ms.CurrentVersion And scr.TargetType = 1 And svce.PeripheralNumber = Value
Select New With {Key .Service = svce.PeripheralNumber,
Key .ScriptName = ms.EnterpriseName,
Key .Peripheral = p.EnterpriseName,
Key .SkillMapping = sg.PeripheralNumber,
Key .LatestVersion = s.Version,
Key .Created = s.DateTime,
Key .Author = s.Author}).ToList
Return valQ
End Get
Set(value As IEnumerable)
End Set
End Property
Now this does return results but they look like this:
Ideally I'd like to be able to do this:
<table>
For Each Item In Model.ByVDN
Dim i = Item
<tr>
<td>#Html.DisplayFor(Function(m) i.Service)</td>
<td>#Html.DisplayFor(Function(m) i.ScriptName)</td>
<td>#Html.DisplayFor(Function(m) i.Peripheral)</td>
Next
etc...
You can't pass about anonymous objects. Well, you can, but it is not strongly typed. You'll have to define a class with these properties, create IEnumerable of instances of that class and pass that Enumerable to the view. There is no other way.
UPD: see similar question: passing linq select query to the method

Grouping by multiple columns

I am not sure if the title is misleading but I wasn't sure how to summarise this one.
I have a table in an SQL DB where a record exists as below:
I would like to display the measurement values of this item in a gridview as below:
I thought about selecting the target values to a list (and the same for the actual values) as below:
Dim cdc As New InternalCalibrationDataContext
Dim allTargetvalues = (From i In cdc.int_calibration_records
Where i.calibration_no = Request.QueryString(0) And
i.calibration_date = Request.QueryString(1)
Select i.measure1_target, i.measure2_target, i.measure3_target).ToList()
Then joining the lists together in some way although I am unsure of how I could join the lists or even if this is the correct approach to be taking?
Well, let me first say that measure1_target, measure2_target, etc. is almost always indicative of bad database design. These should probably be in another table as the "many" end of a 1-to-many relationship with the table you posted. So to answer one of your questions: No, this is not the correct approach to be taking.
With the structure of your table in its current state, your best option is probably something like this:
Dim cdc As New InternalCalibrationDataContext
Dim allTargetValues As New List(Of Whatever)
For Each targetValue In (From i In cdc.int_calibration_records
Where i.calibration_no = Request.QueryString(0) AndAlso
i.calibration_date = Request.QueryString(1)
Select i)
allTargetValues.Add(New Whatever With {.MeasureNumber = 1,
.Target = targetValue.measure1_target,
.Actual = targetValue.measure1_actual })
allTargetValues.Add(New Whatever With {.MeasureNumber = 2,
.Target = targetValue.measure2_target,
.Actual = targetValue.measure2_actual })
allTargetValues.Add(New Whatever With {.MeasureNumber = 3,
.Target = targetValue.measure3_target,
.Actual = targetValue.measure3_actual })
Next
The Whatever class would look like this:
Public Class Whatever
Public Property MeasureNumber As Integer
Public Property Target As Integer
Public Property Actual As Integer
End Class

LINQ GroupBy Usage

I am using this to get all my records ordered by date:
Dim myData = db.Tbl_Exercises.Where(Function(x) x.Exercise_Employee_ID).OrderBy(Function(x) x.Exercise_Create_Date)
I loop through with this:
For Each i As Tbl_Exercise In myData
data.Add(New Object() {i.Tbl_Exercise_Type.ExType_Desc, i.Exercise_Duration})
Next
How can I group by i.Tbl_Exercise_Type.ExType_Desc so I don't have duplicates?
I tried this:
Dim myData = db.Tbl_Exercises.Where(Function(x) x.Exercise_Employee_ID).GroupBy(Function(x) x.Exercise_Type_ID)
But, I don't know how to access the variables within my loop.
Thank you.
Edit:
<EmployeeAuthorize()>
Function ExercisePieChartData() As JsonResult
' get current employee's id
Dim db1 As EmployeeDbContext = New EmployeeDbContext
Dim user1 = db1.Tbl_Employees.Where(Function(e) e.Employee_EmailAddress = User.Identity.Name).Single()
Dim empId = user1.Employee_ID
Dim activityGroups = db.Tbl_Exercises.Where(Function(x) x.Exercise_Employee_ID = empId).GroupBy(Function(x) x.Exercise_Type_ID)
Dim data = New List(Of Object)
' columns (headers)
data.Add(New Object() {"Type", "Duration"})
' Iterate through each collection of activities, grouped by activity types
For Each group In activityGroups
' Iterate through each Tbl_Exercise in the group
For Each activity In group
' Do something with an individual element
data.Add(New Object() {activity.Tbl_Exercise_Type.ExType_Desc, activity.Exercise_Duration})
Next
Next
Return Json(data, JsonRequestBehavior.AllowGet)
End Function
Edit:
' Iterate through each collection of activities, grouped by activity types
For Each group In activityGroups
Dim type = ""
Dim duration = 0
' Iterate through each Tbl_Exercise in the group
For Each activity In group
' Do something with an individual element
type = activity.Tbl_Exercise_Type.ExType_Desc
duration += activity.Exercise_Duration
Next
data.Add(New Object() {type, duration})
Next
Note: Your example isn't entirely clear, so I'm going to make a few assumptions about what you are trying to do with my solution. I'll modify it as needed as more details are made available.
From what it looks like, for each employee you are trying to get a collection of types of exercise that they have performed, and with each type of exercise you would also like a collection of the lengths of time that they spent performing these activities.
I'm going to assume that a row in Tbl_Exercises looks like this:
Public Class Tbl_Exercise
Public Property Exercise_Employee_ID As Integer
Public Property Exercise_Type_ID As Integer
Public Property Exercise_Type_Desc As String
Public Property Exercise_Duration As Integer
End Class
The attempt you make at the end is pretty close, you just need to actually use the grouping once you've created it.
What the GroupBy method has returned you here is actually an IGrouping(Of Integer, Tbl_Exercise) where the key is the Exercise_Type_ID and the value is a collection of rows that are grouped by the key. To access them its pretty simple, you just have to think of the groupings as a sort of nested collection:
Dim activityGroups = db.Tbl_Exercises.Where(Function(x) x.Exercise_Employee_ID = employeeId).GroupBy(Function(x) x.Exercise_Type_ID)
' Iterate through each collection of activities, grouped by activity types
For Each group In activityGroups
' Iterate through each Tbl_Exercise in the group
For Each activity In group
' Do something with an individual element
Console.WriteLine(activity.Exercise_Duration)
Next
Next
Obviously, you may want to do something different than print out individual collections, you may want to data bind each grouping to their own DataGrid so that you can display them separately. You may want to sort each grouping by date, or you may only want the first element from each group. Once you understand how the groupings are structured, it should be pretty easy to accomplish exactly what you're looking for.
Edit:
If you're just looking to aggregate some field in the grouping, this is very simple to accomplish without needing to resort to looping over the results. Simply adding a call to Select on top of your GroupBy will let you project the results into your desired aggregate form:
Dim data = db.Tbl_Exercises _
.Where(Function(x) x.Exercise_Employee_ID = empId) _
.GroupBy(Function(x) x.Exercise_Type_Desc) _
.Select(Function(x)
Return New With {
' x.Key will give you access to the value that the grouping is grouped by
.Exercise_Type_Desc = x.Key,
.TotalDuration = x.Sum(Function(y) y.Exercise_Duration)
}
End Function)