Unable to bind 2 tables to viewModel and send to view - vb.net

table 1. MerchantBusiness
table 2. MerchantServices
i want to display both tables data in a single view.
I want to display the MerchantBusiness details on the view. very basic business name, address etcc.
the MerchantServices is a list of services that the business has.
so i first created the viewModel
Public Class MerchantServicesModel
Public Property MerchantViewModel() As Merchant
Get
Return _Merchant
End Get
Set(value As Merchant)
_Merchant = value
End Set
End Property
Private _Merchant As Merchant
Public Property ServiceViewModel() As IEnumerable(Of MerchantService)
Get
Return _Services
End Get
Set(value As IEnumerable(Of MerchantService))
_Services = value
End Set
End Property
Private _Services As MerchantService
End Class
and in my controller im binding the two tables to the viewModel
Function Index(id As Integer) As ActionResult
Dim db As New MerchantEntities
Dim MerchantDetails As New MerchantServicesModel
MerchantDetails.MerchantViewModel = db.Merchants.Find(id)
MerchantDetails.ServiceViewModel = (From m In db.MerchantServices
Where m.MerchantID = id
Select m).ToList()
Return View(MerchantDetails)
End Function
My View
#ModelType MerchantServicesModel
#Code
Layout = "~/Views/Shared/_Layout.vbhtml"
End Code
#Html.DisplayFor(Function(model) model.MerchantViewModel.BusinessName)
#For Each item In Model.ServiceViewModel
#Html.DisplayFor(Function(model) item.ServiceName)
Next
i was thinking that the MerchantBusiness is not a full list just details of the particular business
but the MerchantServices is a IEnumerable list so i create a table and style blah blah..
now the error im getting is
Additional information: Unable to cast object of type 'System.Collections.Generic.List`1[VBClassMVC.MerchantService]' to type 'VBClassMVC.MerchantService'.
am i missing something, or am i binding incorrectly?
thank you.

Hay all i manged to fix that. Here is the updated ViewModel
Public Property ServiceViewModel() As IEnumerable(Of MerchantService)
Get
Return _Services
End Get
Set(value As IEnumerable(Of MerchantService))
_Services = value
End Set
End Property
Private _Services As IEnumerable(Of MerchantService)
i needed to add IEnumerable(Of MerchantService) to the _Services Private variable..

Related

how to append one class to another of same in vb.net

PropertyPolicy is a class that defines a collection of several fields/entities. Sometimes two separate functions are needed to build out the collection. (LoadEstateAIN and LoadAIN). I need to combine the results of both classes but have tried concat but get a cast exception. What would work here?
Public Class PropertyPolicy
Private agentfield As Entity
Private aininsuredfield() As Entity
Private billinginfofield As BillingInfo
Private cancellationdatefield As Date
Private claimsfield() As Claims
Public Property Agent As Entity
Get
Return Me.agentfield
End Get
Set(ByVal value As Entity)
Me.agentfield = value
End Set
End Property
Public Property AINInsured() As Entity()
Get
Return Me.aininsuredfield
End Get
Set(ByVal value As Entity())
Me.aininsuredfield = value
End Set
End Property
Public Property BillingInfo As BillingInfo
Get
Return Me.billinginfofield
End Get
Set(ByVal value As BillingInfo)
Me.billinginfofield = value
End Set
End Property
Public Property CancellationDate As Date
Get
Return Me.cancellationdatefield
End Get
Set(ByVal value As Date)
Me.cancellationdatefield = value
End Set
End Property
Public Property Claims() As Claims()
Get
Return Me.claimsfield
End Get
Set(ByVal value As Claims())
Me.claimsfield = value
End Set
End Property
End Class
Dim propTemp1 As New PropertyPolicy
Dim propTemp2 As New PropertyPolicy
Dim propTempComb As New PropertyPolicy
propTemp1.AINInsured = LoadEstateAIN(policyid, asofDate, lob, NINclientid, estatecompany)
propTemp2.AINInsured = LoadAIN(policyid, asofDate, lob, NINclientid, estatecompany)
propTempComb.AINInsured = propTemp1.AINInsured.Concat(propTemp2.AINInsured)
The result of Concat is not an array; it is an IEnumerable(Of T). In your case it is an IEnumerable(Of Entity). You just need to add ToArray() to the end of the Concat if you want to assign it back to an array.
propTempComb.AINInsured = propTemp1.AINInsured.Concat(propTemp2.AINInsured).ToArray()
Breaking down this line of code:
[instance3].[property] = [instance1].[property].Concat([instance2].[property])
Assigns the result of the Concat to the property, but the property is an array so you need to change the result of Concat which is an IEnumerable(Of Entity) into an array which is trivial with ToArray.
I could go further and recommend that you don't use arrays as public members, rather IEnumerable. Also, auto-properties would be a better choice for some of these Public/Public properties.
Public Class PropertyPolicy
Private aininsuredfield As Entity()
Private claimsfield As Claims()
Public Property Agent As Entity
Public Property BillingInfo As BillingInfo
Public Property CancellationDate As Date
Public Property AINInsured() As IEnumerable(Of Entity)
Get
Return aininsuredfield
End Get
Set(value As IEnumerable(Of Entity))
aininsuredfield = value.ToArray()
End Set
End Property
Public Property Claims() As IEnumerable(Of Claims)
Get
Return claimsfield
End Get
Set(value As IEnumerable(Of Claims))
claimsfield = value.ToArray()
End Set
End Property
End Class
And btw, that would cause your original code to work without ToArray()
propTempComb.AINInsured = propTemp1.AINInsured.Concat(propTemp2.AINInsured)

Predefined class properties if need expand or shrink quantity of them on each app start

Public Class Products
Private zCriteria As String
Public Property Criteria As String
Get
Return zCriteria
End Get
Set(value As String)
zCriteria = value
End Set
End Property
Private zProductList As New List(Of Product)
Public Property ProductList As List(Of Product)
Get
Return zProductList
End Get
Set(value As List(Of Product))
zProductList = value
End Set
End Property
End Class
Public Class Product
Private zCriteriaList As List(Of Criterias)
Public Property CriteriaList As List(Of Criterias)
Get
Return zCriteriaList
End Get
Set(value As List(Of Criterias))
zCriteriaList = value
End Set
End Property
End Class
Public Class Criterias
Private zCrPropName As String
Public Property CrPropName As String
Get
Return zCrPropName
End Get
Set(value As String)
zCrPropName = value
End Set
End Property
Private zCritCode As String
Public Property CritCode As String
Get
Return zCritCode
End Get
Set(value As String)
zCritCode = value
End Set
End Property
Private zcrPropValue As String
Public Property crPropValue As String
Get
Return zcrPropValue
End Get
Set(value As String)
zcrPropValue = value
End Set
End Property
End Class
For Each oProducts As Products In oAssigment.ProductsList
For Each oproduct As Product In oProducts.ProductList
For Each cr As Criterias In oproduct.CriteriaList
cr.CrPropName = "Product Name" 'some object property name
cr.CritCode = "PN"
cr.crPropValue = "" ' Value of property "Product Name"
Next
Next
Next
It is all made to have different properties of some object depending on options set in text file. It is only a sample o usage.
conditions:
Criterias on applications start is same for all objects (=Product) i want to read.
Every time on start, application read options file where is defined few property names and codes (values i want get from objects). So every run can be initiated different quantity of properties to read. It means i can not have hard-coded names of properties.
Someone can advice me how to predefine "CrPropName" and "CritCode" on app start so many times how much property names defined in options and after that populate it so many times as how many objects exist from which i read these property values.
p.s. I am not very professional at coding and sorry for my language

For a combobox with item = a datarow, how to point ValueMember to one of it's columns

I add items to a combobox like this:
For each R as DataRow in MyDataTable.Rows
If R("ID") > 10 then MyCombo.Items.Add(R)
Next
And now I need to set the DisplayMember and ValueMember to a column of the datarow:
MyCombo.ValueMember = R("ID")
MyCombo.DisplayMember = R("Name")
I know it doesn't make sence to to use "R" as it doesn't reference to anything at this point but it's just to make an indication of what I mean ;-)
The documentation for ValueMember says:
"A String representing a single property name of the DataSource property value, or a hierarchy of period-delimited property names that resolves to a property name of the final data-bound object"
I know I can add the rows to a new datatable and set it to the DataSource, but as you can add any object to the combobox items, it would be nice to use the rows directly, just can't figures out how to make a reference the particular column as a string.?
Maybe you cannot use a row object directly. I guess to use Valuemember you need your item objects to be wrapped in a collection which implement an ilist interface.
In the old MS-Access days combobox items had natively Display- and ValueMember properties, I've always missed that in the .Net combobox control.
My work-around is to use this class, which then can be used for all your ComboBoxes:
Class oComboItems
Public items As New List(Of oDVpairs)
Class oDVpairs
Implements IComparable(Of oDVpairs)
Private myDM As String
Private myVM As Object
Sub New(DM As String, VM As Object)
myDM = DM
myVM = VM
End Sub
Public ReadOnly Property DM() As String
Get
Return myDM
End Get
End Property
Public ReadOnly Property VM() As Object
Get
Return myVM
End Get
End Property
Public Function CompareTo(other As oDVpairs) As Integer Implements IComparable(Of oDVpairs).CompareTo
Return Me.myDM.CompareTo(other.myDM)
End Function
End Class
Public Sub AddItems(DisplayMember As String, ValueMemeber As Object)
items.Add(New oDVpairs(DisplayMember, ValueMemeber))
End Sub
Public ReadOnly Property DisplayMember() As String
Get
Return "DM"
End Get
End Property
Public ReadOnly Property ValueMember() As Object
Get
Return "VM"
End Get
End Property
End Class
And now add my datarows(or any other objects) to the ComboBox:
Dim CI As New oComboItems
For Each R As DataRow In DT_U.Rows
If R("medlnr") > 10 Then
CI.AddItems(R("name"), R("ID"))
end if
Next
CI.items.Sort()
MyCombo.DataSource = CI.Items
MyCombo.DisplayMember = CI.DisplayMember
MyCombo.ValueMember = CI.ValueMember

LongListSelector selecteditem

I have a LongListSelector in an .xaml and I am able to fill it by binding to a an ItemSource when the source is filled by a DataContext using a single table from my SQL Server CE database like this:
Dim row = (From rows In db.Hub
Order By rows.HubID Descending
Select rows).ToList()
Me.MainLongListSelector.ItemsSource = row
I am thus able to get the ID of the selected item as follows:
HubID = CType(MainLongListSelector.SelectedItem, Hub).HubID
I am also able to bind to a 'query' DataSource as follows:
Dim row = (From ac In db.Activity
Join at In db.ActivityType On ac.ActivityTypeID Equals at.ActivityTypeID
Select New With {.ID = ac.ActivityID,
.Title = ac.Activity1}).ToList()
Me.MainLongListSelector.ItemsSource = row
however, since this is not referring to a specific table in the DataContext, I cannot get the ID using the above code, ie:
Dim ActID = CType(MainLongListSelector.SelectedItem, Activity).ActivityID '- returns nothing
How should I get the value(s) of selectedItem in this case?
NB: I have created the anonymous fields (.ID and .Title) because those are the names I have bound in the xaml, so the LongListSelected gets populated without writing extra code.
Thanks
Phew!!
I discovered that two things:
this HubID = CType(MainLongListSelector.SelectedItem, Hub).HubID is calling a List (Of DataContext), while in the second scenario above I am using a List (Of Anonymous). So I searched for List (Of Anonymous) and this came up!
I now know I can create a class for List (Of Anonymous) and properly name its properties, thus make it available outside its methods, like in my 'query' question above.
So the answer is I created the class for my anonymous list, declared its properties
Public Class AnonList
Private _id As Integer
Public Property ID() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Private _title As String
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property
Private _desc As String
Public Property Desc() As String
Get
Return _desc
End Get
Set(ByVal value As String)
_desc = value
End Set
End Property
End Class
and therefore assigned them to the ItemSource values,
Select New AnonList With {.ID = ac.ActivityID,
thus being able to get the SelectedItem values as required:
ActivityID = CType(MainLongListSelector.SelectedItem, AnonList).ID
Took a bit of determination to figure that out!

How to use instance of New Object in With... Block

Dim objects As New List(Of Object)
With New Object
.prop1 = "Property 1"
.prop2 = "Property 2"
objects.add(.instance) 'i mean instance of New Object
End With
is it possible.
I ask new question because last question has mislead information and I don't give right answer. so here code.
No it is not possible. The With statement basically creates an implicit variable. All you can do with that variable is access members and there is no member that returns a reference to the object itself.
If you want succinct code to create, populate and add an object to a list then do this:
myList.Add(New SomeType With {.SomeProperty = someValue,
.SomeOtherProperty = someOtherValue})
Interestingly, you can make it work the way you wanted if you create your own extension method. I was under the impression that you could not extend the Object class but either I was wrong or that has changed because I just tried in VB 2013 and it worked. You can write a method like this:
Imports System.Runtime.CompilerServices
Public Module ObjectExtensions
<Extension>
Public Function Self(Of T)(source As T) As T
Return source
End Function
End Module
and then do something like this:
With New SomeType
.SomeProperty = someValue
.SomeOtherProperty = someOtherValue
myList.Add(.Self())
End With
I'm not sure that that really provides any benefit though, given the availability of the object initialiser syntax that I demonstrated first.
Hmmm... I just realised that that's not actually extending the Object class. It was my original intention to try to do so but then I realised that a generic method was better because it would then return the same type as you call it on. I did just test it with a non-generic method extending type Object and it did still worked though.
You should to create your own class By example :
Public Class Car
Private _NumberCar As Integer
Public Property NumberCar() As Integer
Get
Return _NumberCar
End Get
Set(ByVal value As Integer)
_NumberCar = value
End Set
End Property
Private _ColorCar As Color
Public Property ColorCar() As Color
Get
Return _ColorCar
End Get
Set(ByVal value As Color)
_ColorCar = value
End Set
End Property
Private _OwnerName As String
Public Property OwnerName() As String
Get
Return _OwnerName
End Get
Set(ByVal value As String)
_OwnerName = value
End Set
End Property
End Class
and in the Class where you want to add the cars object do this :
Dim CarList As New List(Of Car)
Dim item As New Car
With item
.NumberCar = 1243
.ColorCar = Color.Red
.OwnerName = "Ibra"
End With
CarList.Add(item)
strong text