Struggling with VB .net Lambdas - vb.net

I'm trying to use lambdas in some VB.Net code, essentially I'm trying to set a flag when databound is called.
Simplified it looks like this:
Dim dropdownlist As New DropDownList()
dropdownlist.DataSource = New String() {"one", "two"}
Dim databoundCalled As Boolean = False
AddHandler dropdownlist.DataBound, Function(o, e) (databoundCalled = True)
dropdownlist.DataBind()
My understanding is that the databoundCalled variable should be set to true, clearly I'm missing something as the variable always remains false.
What do I need to do to fix it?

After looking over your code and scratching my head, I found a solution that works. Now, why this works over what you have, I am not clear. Maybe this will at least help you in the right direction. The key difference is I have a method that sets the value to true/false. Everything else is the same.
Here is my entire web project code:
Partial Public Class _Default
Inherits System.Web.UI.Page
Dim databoundCalled As Boolean = False
Dim dropdownlist As New DropDownList()
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Response.Write(databoundCalled)
Bind()
Response.Write(databoundCalled)
End Sub
Sub Bind()
AddHandler dropdownlist.DataBound, Function(o, e) (SetValue(True))
dropdownlist.DataSource = New String() {"one", "two"}
dropdownlist.DataBind()
End Sub
Function SetValue(ByVal value As Boolean) As Boolean
databoundCalled = value
Return value
End Function
End Class
I hope this helps!

Single line Lambdas in vb.net ALWAYS are expressions , what your lambda expression is doing is basically saying does databoundCalled = True or (databoundCalled == True) if your a c# guy , not set databoundCalled = True

The problem is how lambdas are interpreted. In VS2008 a Function lambda is always interpreted as an expression and not a statement. Take the following block of code as an example
Dim x = 42
Dim del = Function() x = 32
del()
In this case, the code inside the lambda del is not doing an assignment. It is instead doing a comparison between the variable x and the value 32. The reason why is that VB has no concept of an expression that is an assignment, only a statement can be an assignment in VB.
In order to do an assignment in a lambda expression you must have statement capabilities. This won't be available until VS2010 but when it is you can do the following
Dim del = Function()
x = 32
End Function
Essentially anything that is not a single line lambda is interpreted as a statement.

Related

VB.NET Sub inside of a Function? What is this?

So I'm reading through my source code looking for places to improve the code when I come across this unholy chunk of code.
Public Function ReadPDFFile(filePath As String,
Optional maxLength As Integer = 0) As List(Of String)
Dim sbContents As New Text.StringBuilder
Dim cArrayType As Type = GetType(PdfSharp.Pdf.Content.Objects.CArray)
Dim cCommentType As Type = GetType(PdfSharp.Pdf.Content.Objects.CComment)
Dim cIntegerType As Type = GetType(PdfSharp.Pdf.Content.Objects.CInteger)
Dim cNameType As Type = GetType(PdfSharp.Pdf.Content.Objects.CName)
Dim cNumberType As Type = GetType(PdfSharp.Pdf.Content.Objects.CNumber)
Dim cOperatorType As Type = GetType(PdfSharp.Pdf.Content.Objects.COperator)
Dim cRealType As Type = GetType(PdfSharp.Pdf.Content.Objects.CReal)
Dim cSequenceType As Type = GetType(PdfSharp.Pdf.Content.Objects.CSequence)
Dim cStringType As Type = GetType(PdfSharp.Pdf.Content.Objects.CString)
Dim opCodeNameType As Type = GetType(PdfSharp.Pdf.Content.Objects.OpCodeName)
Dim ReadObject As Action(Of PdfSharp.Pdf.Content.Objects.CObject) = Sub(obj As PdfSharp.Pdf.Content.Objects.CObject)
Dim objType As Type = obj.GetType
Select Case objType
Case cArrayType
Dim arrObj As PdfSharp.Pdf.Content.Objects.CArray = DirectCast(obj, PdfSharp.Pdf.Content.Objects.CArray)
For Each member As PdfSharp.Pdf.Content.Objects.CObject In arrObj
ReadObject(member)
Next
Case cOperatorType
Dim opObj As PdfSharp.Pdf.Content.Objects.COperator = DirectCast(obj, PdfSharp.Pdf.Content.Objects.COperator)
Select Case System.Enum.GetName(opCodeNameType, opObj.OpCode.OpCodeName)
Case "ET", "Tx"
sbContents.Append(vbNewLine)
Case "Tj", "TJ"
For Each operand As PdfSharp.Pdf.Content.Objects.CObject In opObj.Operands
ReadObject(operand)
Next
Case "QuoteSingle", "QuoteDbl"
sbContents.Append(vbNewLine)
For Each operand As PdfSharp.Pdf.Content.Objects.CObject In opObj.Operands
ReadObject(operand)
Next
Case Else
'Do Nothing
End Select
Case cSequenceType
Dim seqObj As PdfSharp.Pdf.Content.Objects.CSequence = DirectCast(obj, PdfSharp.Pdf.Content.Objects.CSequence)
For Each member As PdfSharp.Pdf.Content.Objects.CObject In seqObj
ReadObject(member)
Next
Case cStringType
sbContents.Append(DirectCast(obj, PdfSharp.Pdf.Content.Objects.CString).Value)
Case cCommentType, cIntegerType, cNameType, cNumberType, cRealType
'Do Nothing
Case Else
Throw New NotImplementedException(obj.GetType().AssemblyQualifiedName)
End Select
End Sub
Using pd As PdfSharp.Pdf.PdfDocument = PdfSharp.Pdf.IO.PdfReader.Open(filePath, PdfSharp.Pdf.IO.PdfDocumentOpenMode.ReadOnly)
For Each page As PdfSharp.Pdf.PdfPage In pd.Pages
ReadObject(PdfSharp.Pdf.Content.ContentReader.ReadContent(page))
If maxLength > 0 And sbContents.Length >= maxLength Then
If sbContents.Length > maxLength Then
sbContents.Remove(maxLength - 1, sbContents.Length - maxLength)
End If
Exit For
End If
sbContents.Append(vbNewLine)
Next
End Using
'Return sbContents.ToString
Dim ReturnList As New List(Of String)
For Each Line In sbContents.ToString.Split(vbNewLine)
If String.IsNullOrWhiteSpace(Line.Trim) Then
Else
ReturnList.Add(Line.Trim)
End If
Next
Return ReturnList
End Function
All this does is read the text parts of a PDF using PDFSharp. What caught my eye however was line 17. Is that a Sub inside of the function?
So, what exactly is this Sub inside of a function? I didn't write this code so I've never seen anything like this before.
How does this work exactly and why wouldn't I use a function to do the processing and then return the results?
In short, my question is, what is this, how does it work, and why would I want to use something like this?
That's a so-called Lambda expression. They're used to create inline (or more correctly: in-method) methods, which makes them more dynamic than normal methods.
In your example a lambda expression is not necessary and only makes the code harder to understand. I suppose the author of that code wrote a lambda expression instead of a separate method in order to not expose ReadObject to any outside code.
One of the best uses for a lambda expression IMO is when you want to make thread-safe calls to the UI thread, for instance:
If Me.InvokeRequired = True Then
Me.Invoke(Sub() TextBox1.Text = "Process complete!")
Else
TextBox1.Text = "Process complete!"
End If
...where the same code without a lambda would look like this:
Delegate Sub UpdateStatusTextDelegate(ByVal Text As String)
...somewhere else...
If Me.InvokeRequired = True Then
Me.Invoke(New UpdateStatusTextDelegate(AddressOf UpdateStatusText), "Process complete!")
Else
UpdateStatusText("Process complete!")
End If
...end of somewhere else...
Private Sub UpdateStatusText(ByVal Text As String)
TextBox1.Text = Text
End Sub
There are also other examples where lambda expressions are useful, for instance if you want to initialize a variable but do some processing at first:
Public Class Globals
Public Shared ReadOnly Value As Integer = _
Function()
DoSomething()
Dim i As Double = CalculateSomething(3)
Return Math.Floor(3.45 * i)
End Function.Invoke()
...
End Class
Yet another usage example is for creating partially dynamic event handlers, like this answer of mine.

Pass integer value from one form to another in VB.NET

I'm writing a program that has two forms. One form gets the user to enter multiple values, and then does some calculations. Then it passes that information to another form However I can't figure out how to do it. Here is a relevant part of my code. To head some confusion, I am trying to pass 11 values, also initially, form 2 is not shown, and then when the values are passed from form 1 to form 2, then form 1 goes away and form 2 is the only one that shown
NOTE: This is not all my code, I don't believe all my code is required (I have 1000 lines right now) However this is the code with the information I want to be passed to the other form.
A lot of people are apparently saying that this is a duplicate of another question, however that question, he seems to already know how to pass the variables, but is just having issues with it (and even with looking at his, i cant figure it out)
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
'declarations
Dim intNormal As Integer
Dim intChildren As Integer
Dim intBonanza As Integer
Dim intDiamond As Integer
Dim intPictureFrame As Integer
Dim intKite As Integer
Dim intCrazyT As Integer
Dim intLetterX As Integer
Dim int2PostageStamp As Integer
Dim intPick7 As Integer
Dim intJackpot As Integer
Validate()
If txtNormal1.Enabled = False Then
intNormal = intNormInput
Else
intNormal = CalcNormalBooks()
End If
If txtChildren1.Enabled = False Then
intChildren = intChildInput
Else
intChildren = calcChildrensBooks()
End If
If txtBonanza1.Enabled = False Then
intBonanza = intBonInput
Else
intBonanza = calcBonanza()
End If
If txtSpecial1.Enabled = False Then
intSpecial = intSpeInput
Else
intSpecial = calcSpecialBooks(intSpecial)
End If
If txtDiamond1.Enabled = False Then
intDiamond = intDiaInput
Else
intDiamond = calcDiamond(intSpecial)
End If
If txtPictureFrame1.Enabled = False Then
intPictureFrame = intPicInput
Else
intPictureFrame = calcPictureFrame(intSpecial)
End If
If txtKite1.Enabled = False Then
intKite = intKiteInput
Else
intKite = calcKite(intSpecial)
End If
If txtCrazyT1.Enabled = False Then
intCrazyT = intCrazyInput
Else
intCrazyT = calcCrazyT(intSpecial)
End If
If txtLetterX1.Enabled = False Then
intLetterX = intLettInput
Else
intLetterX = calcLetterX(intSpecial)
End If
If txt2PostageStamp1.Enabled = False Then
int2PostageStamp = intPostInput
Else
int2PostageStamp = CalcPostageStamp(intSpecial)
End If
If txtPick71.Enabled = False Then
intPick7 = intPickInput
Else
intPick7 = calcPick7(intSpecial)
End If
If txtJackpot1.Enabled = False Then
intJackpot = intJackInput
Else
intJackpot = calcJackpot()
End If
End Sub
Since I had almost the same requiremnt lately here is my solution:
Custom Event which fires when your 2nd Form is closing
Public Event HotKeyFormClosed As EventHandler(Of HotKeyFormClosedEventArgs)
Custom EventArgs class where you store your values you want to pass to Main Form
Public Class HotKeyFormClosedEventArgs
Inherits EventArgs
'Your properties here
Public Sub New(...) 'your params here
MyBase.New()
'set your properties here
End Sub
End Class
On 2nd Form handle FormClosed event and pass your values to EventArgs
Private Sub HotKey_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs)
RaiseEvent HotKeyFormClosed(Me, New HotKeyFormClosedEventArgs(...)) 'your params here
End Sub
On Main Form handle your custom event (here HotKeyFormClosed) and extract its values
AddHandler frmHotKey.HotKeyFormClosed, AddressOf HotKey_FormClosed;
...
Private Sub HotKey_FormClosed(sender As Object, e As HotKeyFormClosedEventArgs)
'Do stuff with values from e
End If
I have chosen the Event approach since it decouples the two forms from another.
One could easily duplicate the information on both forms, make them public and access it directly thru an object instance.
But I like the observable approach from the events more due to it gives mor flexibility (additonal forms using the same events etc.)
P.S.: I wrote my code in c# and blind entered the VB code here so be gracious.
The values/variables that a method expects to receive (specified in the method's signature) are called Parameters.
The values sent to a method when the method is called are called Arguments.
As long as the arguments used when calling a method match the parameters for that method, those values can be passed.
For example (and I'll try to apply this to your context), if you want to create an instance of a form that takes certain values, you can specify those parameters in the form's New event, like so:
Public Sub New(someInt As Integer)
'do something with someInt here
End Sub
Then when you call this method you'd pass it the arguments, like so:
Dim myInt As Integer = 10
Dim newForm As myForm = New myForm(myInt)
When I say the arguments need to match the parameters, that means the number of values, the order of those values, and the value types must be the same (or in the case of numbers the parameter's type must be the same or larger than the argument's type).
As long as that is true, then it shouldn't really matter how you pass these - you could pass 11 individual arguments, you just have to make sure you are matching the argument to the parameter.
Hope that helps!

Function return string or boolean

I want a function to return a String or Boolean. Something like this:
Public Function GetString(Byval What As String) 'As... someting?
If (What = "A") Then
Return "String to return"
Else if (What = "B") Then
Return True
End If
Return False 'Nothing to return
End Function
How can i now do this? If i ask like
If GetString("A") Then
MsgBox(GetString())
End IF
...it returns a string and of course it gives an error on converting string to bool.
I could always return strings and checks it lengths, but it feels bad. Or maybe I'm just into PHP too much?
But is there a way to do it more like this? If i ask for "B" i know it would return a bool, if i ask for "A" i want to alert the string if there was any and so on.
How can i now do this?
You can't.
A function can only return one type, not multiple.
You can return a custom type that contains a string and a boolean.
I would use an Array list. You can store whatever type you need in the list and then parse it on the return. This is really not best practice as explained above, but when you gotta get things done... The end justifies the means. Not recommended.
Public Function GetString(Byval What As String) As ArrayList
Dim b as boolean = True
dim myArrayList as Arraylist = New ArrayList
If (What = "A") Then
ArrayList.Add("String to return")
Else if (What = "B") Then
ArrayList.Add(b)
End If
Return False 'Nothing to return
End Function
Proof of concept below:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim a As Boolean = True
Dim myarraylist As ArrayList = New ArrayList
myarraylist.Add(a)
myarraylist.Add("g")
Debug.WriteLine(myarraylist.GetType.ToString)
Debug.WriteLine(myarraylist(0).GetType.ToString)
Debug.WriteLine(myarraylist(1).GetType.ToString)
If myarraylist(0).GetType.ToString = "System.string" Then
Debug.WriteLine("Function returned a String")
ElseIf myarraylist(0).GetType.ToString = "System.boolean" Then
Debug.WriteLine("Function returned a Boolean")
End If
End Sub
You can return Object, but it is considered very bad form for a function to return 2 data types.
As Oded said, you can't return more than one parameter from a function.
It is not too clear what you are doing from your code example, but you may look into passing parameters by reference. As pointed out in the answer there, passing a parameter by reference is useful for:
when you want to return a state or status of an operation plus the result from the operation.
This is how int.TryParse and similar methods work.

Using Moq's VerifySet in VB.NET

I have a function that updates a user in the asp.net membership provider.
<AcceptVerbs(HttpVerbs.Post)>
Public Function EnableUser(ByVal id As String) As JsonResult
Dim usr As StargatePortalUser = _membershipService.GetUser(id, Nothing)
usr.IsApproved = True
_membershipService.UpdateUser(usr)
Dim response As New AjaxResponse(usr.UserName)
Return Json(response)
End Function
I am trying to test this function to ensure the IsApproved property is set correctly
<TestMethod()>
Public Sub Service_Can_Enable_A_User_Account()
' Arrange
Dim usr As New Mock(Of MembershipUser)
usr.SetupProperty(Function(u) u.IsApproved)
_membershipService.Setup(Function(m) m.GetUser(It.IsAny(Of String), It.IsAny(Of Boolean))).Returns(usr.Object)
Dim target As New UsersController(_membershipService.Object)
target.ControllerContext = New ControllerContext(FakeAuthenticatedHttpContext("testuser", String.Empty, True, True, False), New RouteData, target)
' Act
Dim actual As JsonResult = target.EnableUser("userId")
' Assert
Assert.IsTrue(DirectCast(actual.Data, AjaxResponse).Success)
_membershipService.Verify(Sub(m) m.UpdateUser(It.IsAny(Of MembershipUser)), Times.Once)
usr.Verify(Function(u) u.IsApproved = True)
End Sub
When I try to verify that the IsApproved property has been set to True an exception is returned:
System.ArgumentException: Expression is not a method invocation: u => (u.IsApproved == True)
There are so few examples of using Moq in VB that I can't figure this out, any help would be appreciated.
This is an ASP.NET MVC2 app in VB.NET 10 (.NET 4.0)
EDIT:
Ok, turns out it's not quite so straight forward in VB.
usr.Verify(Function(u) u.IsApproved = True)
needs to be
usr.VerifySet(Function(u) InlineAssignHelper(u.IsApproved, True))
and you need to add the following function:
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
FURTHER EDIT:
Thinking around the problem I arrived at a more simple solution. I changed
Dim usr As New Mock(Of MembershipUser)
usr.SetupProperty(Function(u) u.IsApproved)
_membershipService.Setup(Function(m) m.GetUser(It.IsAny(Of String), It.IsAny(Of Boolean))).Returns(usr.Object)
for
Dim usr As New Mock(Of MembershipUser)
usr.SetupProperty(Function(u) u.IsApproved)
Dim usrObj = usr.Object
_membershipService.Setup(Function(m) m.GetUser(It.IsAny(Of String), It.IsAny(Of Boolean))).Returns(usrObj)
and then can replace
usr.VerifySet(Function(u) InlineAssignHelper(u.IsApproved, True))
with the more straightforward
Assert.IsTrue(usrOb.IsApproved)
Sometimes I just don't see the simple solution :)
You want to use the following (from http://code.google.com/p/moq/wiki/QuickStart):
// or verify the setter directly
mock.VerifySet(foo => foo.Name = "foo");
Right now the thing that you're feeding in is a comparison rather than an assignment, so even if Moq did process the statement without an exception, it would still not be Doing What You Mean.
Well this may be a little late, but I was facing the same problem and the solution was way simpler then using a InlineAssignHelper method.
Just change the Function to a Sub and it should work.
So try this instead:
usr.VerifySet(Sub(u) u.IsApproved = True)

Using Delegates for handling an event

Sorry, that's the best subject I can come up with, if I understood the solution better, I could probably phrase a better subject line.
I am using a great grid control, Super List,l located here:
http://www.codeproject.com/KB/list/outlooklistcontrol.aspx?fid=449232&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=276
Before you read the problem, please note that you can download a very small VB.NET 2005 sample app which demos the problem:
http://dokmanovich.com/Documents/SuperListEvents.zip
Getting the answer to my question will, I hope, help me to understand dynamic events better in the context of what I am trying to accomplish.
The grid works like this: When you add a column to the grid, you specify the address of an event handler which will return the value at run time. In this case, the CC_ItemValueAccessor function. The latter function will be called with an input parameter which, in this case, is a "ToDo" object. Each ToDo object will be rendered as one row in the grid. The job of the CC_ItemValueAccessor function is to return the column value to be displayed by the grid for the row that corresponds to the passed-in ToDo object.
This works fine till I take it to the next step:
I want to dynamically create columns at run time. For example, I want to display the output of a datatable returned as a result of executing a user-specified SQL.
Using the earlier described static approach, I have one columnItemValueAccessor function responsible for returning the value of each column in the grid for the passed in row object. Now, since the columns are determined at run time based on the SQL returned results, I believe I need to write a generic handler that handles all columns, determines the name of the column that triggered this event and then returns the value for that column within the row object that is passed in as the sole parameter.
The problem is that the ItemValueAccessor function has a signature that only includes the row object and I do not know of a way to determine which column name is needed since all of the columns were hooked up to the same ItemValueAccessor function as the event handler.
I suspect that this is just a limitation of the control and that to overcome this problem I would have to enhance the underlying custom control, but that is likely beyond my current skills as it is an advanced control written in C# and I am a VB guy.
Here's the code:
Private Sub AddCcColumn()
Dim NewColumn As New BinaryComponents.SuperList.Column("CC", "CC", 110, AddressOf Cc_ItemValueAccessor)
_SuperList.Columns.Add(NewColumn)
End Sub
Private Function Cc_ItemValueAccessor(ByVal rowItem As Object) As Object
Dim ToDo As ToDo = CType(rowItem, SrToDoAndException).ToDo
Return ToDo.CCs.ToString
End Function
'---------------------------
And here are the signatures of the Column's instantiator method and the definition of the last parameter which is responsible for specifying the procedure that handles identifies the event handler responsible for returning the value of the column.
Public Sub New(ByVal name As String, ByVal caption As String, ByVal width As Integer, ByVal columnItemValueAccessor As BinaryComponents.SuperList.ColumnItemValueAccessor)
Member of BinaryComponents.SuperList.Column
Public Sub New(ByVal object As Object, ByVal method As System.IntPtr)
Member of BinaryComponents.SuperList.ColumnItemValueAccessor
Does anyone have any suggestions or am I stuck? I would really love to utilize the fantasic grouping capabilities of this control so I can display dynamic output that allows the user to group the dynamic output of a SQL by any column that they want.
I addressed the question to the author at the above site but it has gone unanswered. This is a desperate attempt to find a way to do this.
Thanks for bearing with me. I hope this question isn't rejected based on the fact that I refer to a third party control. My hope is that the answer lies in a better understanding of delegates, a more universal topic.
I used a lambda function, as Matthew suggested. Here is the code from the dynamic approach:
Private Sub btnDynamic_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDynamic.Click
ListControl1.Columns.Clear()
For Each DataCol As DataColumn In _ds.dtbPerson.Columns
' Get the column name in a loop variable - it needs to be in loop scope or this won\'t work properly'
Dim colName = DataCol.ColumnName
' Create the function that will be called by the grid'
Dim colLambda As ColumnItemValueAccessor = Function(rowItem As Object) General_ItemValueAccessor(rowItem, colName)
' Setup each column in the grid'
Dim NewColumn As New BinaryComponents.SuperList.Column(DataCol.ColumnName, DataCol.ColumnName, 220, colLambda)
ListControl1.Columns.Add(NewColumn)
Next
End Sub
Private Function General_ItemValueAccessor(ByVal rowItem As Object, ByVal colName As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(colName).ToString
End Function
Here's a quick primer on how it works:
Each time through the loop the lambda function is creating a new callback function for each column that looks something like this:
Class Func1
Dim colName1 As String = "PersonId"
Private Function General_ItemValueAccessor1(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.colName1).ToString
End Function
End Class
Class Func2
Dim colName2 As String = "LastName"
Private Function General_ItemValueAccessor2(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.colName2).ToString
End Function
End Class
... for however many columns you have - 3 in this case.
You need the colName variable within the loop and not use just DataCol.ColumnName directly in the lambda. Otherwise, when the grid gets around to calling the callback functions, that DataCol variable would be equal to the last value from the collection (or Nothing) for all the callback functions.
Basically, it would do this and you wouldn't get what you expected:
Class Func
Dim DataCol1 = DataCol
Private Function General_ItemValueAccessor1(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.DataCol1.ColumnName).ToString
End Function
Private Function General_ItemValueAccessor2(ByVal rowItem As Object) As Object
Dim rowPerson As DataRow = CType(rowItem, DataRow)
Return rowPerson.Item(Me.DataCol1.ColumnName).ToString
End Function
...
End Class
Hope that helps. Good luck.
The problem is that the ItemValueAccessor function has a signature that only includes the row object and I do not know of a way to determine which column name is needed since all of the columns were hooked up to the same ItemValueAccessor function as the event handler.
Okay, I haven't used that control in the past, and I'm really a C# person. But I think you may be able to accomplish this by creating a new lambda function for each column. Something like:
Private Sub AddCcColumn(ByVal sender As System.Object As System.String)
colLambda = (Function(rowItem As Object) Cc_InternalItemValueAccessor(columnName, rowItem))
Dim NewColumn As New BinaryComponents.SuperList.Column("CC", "CC", 110, colLambda)
_SuperList.Columns.Add(NewColumn)
End Sub
Then, colLambda will fit the signature, while your internal Cc_InternalItemValueAccessor gets the info it needs. Totally untested, but I think the basic idea works.