How to save a null datetime to SqlServer DB? not working - asp.net

VS-Studio 2012 Web Express, ASP.NET, WebForms , VB , SqlServer , WebSite application having trouble saving a NULL value for DateTime to the strongly typed ROW:
Dim oRowVEHICLES As Main_TblAdap.tVEHICLESRow = odtVEHICLES.Rows(0) ' (0) is the first row.
oRowVEHICLES.[WElectrical] = If(WElectrical.Year < 10, DBNull.Value, WElectrical)
...etc...
Currently the DetailsView template field textbox is < blank> or empty or "" and the BLL function shows it as a date like: #01/01/0001#. So I test the YEAR value of the passed in variable if less than 10 then save DBNull.Value to the oRowVehicles.[WElectrical] but fails since datatype=Date and cannot convert DBNull to Date.
The DB-field is type Date and allows nulls.
The TableAdapter.xsd view shows the default value is < DBNULL>.
So, why is the oRowVehicles not Date nullable?
How do I make the WElectrical column nullable DATE?
I must be overlooking something, because I cannot be the only one to save an optional DATE value to the Sql-DB.
Your comments and solutions are welcome. Thanks...John
EDIT
ASPX code one DATE field in the DetailsView (others are similar):
<asp:TemplateField HeaderText="Electrical End Date" SortExpression="WElectrical">
<EditItemTemplate>
<TGADate:GADate ID="ucdtWElectrical" runat="server" Enabled="True" MinDate="01/01/1980" MaxDate="12/31/2050"
Caption="Electrical End Date" HideCaption="True" Width="100"
IsRequired="false"
UpdateMode="Conditional"
Text='<%# Bind("WElectrical")%>' />
</EditItemTemplate>
<InsertItemTemplate>
<TGADate:GADate ID="ucdtWElectrical2" runat="server" Enabled="True" MinDate="01/01/1980" MaxDate="12/31/2050"
Caption="Electrical End Date" HideCaption="True" Width="100"
IsRequired="false"
UpdateMode="Conditional"
Text='<%# Bind("WElectrical")%>' />
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="lblWElectrical" runat="server" Text='<%# clsGA_Lib1.fnGetDateTextFromObject(Eval("WElectrical"))%>' Style="font-weight: bold;"></asp:Label>
</ItemTemplate>
<ItemStyle Font-Bold="true" />
</asp:TemplateField>
Object DataSource parameter definition in the ASPX.
<asp:Parameter Name="WElectrical" Type="DateTime" />
BLL Code:
<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, False)> _
Public Function UpdateFromDetailsView(ByVal original_UID_VEHICLE As Int32, _
ByVal VehicleNbr As String, _
...other function parameter variables...
ByVal WElectrical As Date, _
...other function parameter variables...
) As Boolean
' Get the new VEHICLE-row instance to be updated.
Dim odtVEHICLES As Main_TblAdap.tVEHICLESDataTable = Adapter.GetVhclByVhclID(original_UID_VEHICLE)
If odtVEHICLES.Count <> 1 Then
' no matching record found, return false
Return False
End If
' Populate the values of the ROW.
Dim oRowVEHICLES As Main_TblAdap.tVEHICLESRow = odtVEHICLES.Rows(0) ' (0) is the first row.
With oRowVEHICLES
...setting row-field values...
.[WElectrical] = If(WElectrical.Year < 10, Nothing, WElectrical)
...etc...
End With
' Update the oRowVEHICLES.
Dim rowsAffected As Integer = Adapter.Update(odtVEHICLES)
' Return TRUE if precisely one row was INSERTED, otherwise false.
Return CBool(rowsAffected = 1)
End Function
Edit comment for above code
The WElectrical parameter coming into the BLL-function is a DATE with a value of #01/01/0001#.
The code to place the value into the ROW-object
.[WElectrical] = If(WElectrical.Year < 10, Nothing, WElectrical)
places Nothing as the row-object-field-value.
The Adapter.Update(odtVEHICLES) updates the Sql-DB.
So what is causing the #01/01/0001# value to be placed into the Sql-DB?
Sql-DB column definition
//////// end of Edit ///////////

do one thing:
change DBNull.Value to Nothing
Alternatively you can change the datatype in the dataset to System.Object, and
go to the properties of that data colm
then you can select '(Nothing)' in the dropdown.
set Null value to >> Nothing

Thanks to all commentators to the above question.
The solution is to change the Row-column-variable to this sentence which casts the Nothing to Date? (nullable) as follows...
.[WElectrical] = If(WElectrical.Year < 10, CType(Nothing, Date?), WElectrical)
AND -- Changed the dataset-column-definition (in the .xsd) as follows:
DataType ==> System.Object (not Date)
NullValue ==> (Nothing) (not Throw Exception)
My sincere thanks to all contributors -- since elements of each of their suggestions have contributed to this solution.
This is the solution for sending a nullable value into the DataRow-column.
Thank you for all your help.

Related

ASP:NET - GridVIEW - DropDownList selectedvalue

I am new at this forum though I have passed many years looking for answers into it. Now,I will like your help to solve an issue. I am following this link to make my own DropDown List in my Grid and works fine until this line:
ddlCities.Items.FindByValue(country).Selected = True
here,I have got error:
Object reference not set to an instance of an object.
but my code is right in affected fields:
this is relevant code in Code Behind:
Protected Sub RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow AndAlso grdLinea.EditIndex = e.Row.RowIndex;
Dim ddlCities As DropDownList = DirectCast(e.Row.FindControl("ddlFacturarA"), DropDownList)
' Create the command with the sproc name and add the parameter required'
ddlCities.DataSource = GetData("select UPPER(DSCA_ZONA)as Zona from tb_personal where dsca_Zona <> 'NULL'group by dsca_zona order by dsca_zona")
ddlCities.DataTextField = "Zona"
ddlCities.DataValueField = "Zona"
ddlCities.DataBind()
'Add Default Item in the DropDownList
'ddlCountries.Items.Insert(0, New ListItem("Please select"))
Dim country As String = Trim(CType(e.Row.FindControl("lblFacturarA"), Label).Text)
ddlCities.Items.FindByValue(country).Selected = True
End If
End Sub
and this is affected code in design mode:
<EditItemTemplate >
<asp:label ID="lblFacturarA" Value ='<%# Eval("facturar_a")%>' Visible ="false" runat="server" />
<asp:DropDownList
ID="ddlFacturarA"
CssClass="txt"
runat="server"
AutoPostBack="True" ValidationGroup="rfNewLineEmpty">
</asp:DropDownList>
<asp:RequiredFieldValidator
ID="rfNewLineFacturarA"
runat="server"
ErrorMessage="Obligatorio"
ValidationGroup="rfNewLine"
SetFocusOnError="True"
ControlToValidate="ddlFacturarA">
</asp:RequiredFieldValidator>
</EditItemTemplate>
I know I am new at ASP.NET and maybe I am loosing something by the way, but I have been round this code for two days and don't see light.
can you tell me something about reason for this error?
please,let me know if you need more detailed information to solve this.
thanks in advance
If you are sure that error is on line ddlCities.Items.FindByValue(country).Selected = True and country item is in dropdown list, I suggest you double check that is there white space or upper/lower case difference in dropdown list item and country variable.
because FindByValue finds exact item and it is case sensitive.
You should try changin query to RTRIM(LTRIM(UPPER(DSCA_ZONA))) as Zona
and
ddlCities.Items.FindByValue(country.ToUpper()).Selected = True
Sorry for delay as I been outside, i think i've solved in this way
Dim country As String = Trim(CType(e.Row.FindControl("lblFacturarA"), Label).Text)
ddlCities.Items.Insert(0, country)
and now it's working fine, Do you think this is a valid way?
many thanks!!!

Specified Cast is not valid when DataBind to Nullable DateTimeOffset and field is NULL

I've created a simple CompositeControl and exposed a Nullable DateTimeOffset property.
I'm binding the control to a SQL Server DateTimeOffset field using
DateTimeOffset='<%# Bind("myDateTimeOffsetField") %>'
This works great when the DateTimeOffset field has a value.
But when the field is NULL I get a "Specified Cast is not valid" error.
How do I stop this error and set my property to Nothing when the field is NULL?
I thought this would be the default behaviour!
Property definition is:
Public Property DateTimeOffset As DateTimeOffset?
Later comment:
I've found that this works if I change from using Bind to:
DateTimeOffset='<%# iif(IsDbNull(Eval("myDateTimeOffsetField")), Nothing, Eval("myDateTimeOffsetField")) %>'
But then I don't get "myDateTimeOffsetField" passed as an argument in the FormView.ItemUpdating event (yes, this is in a FormView control) since ASP.NET assumes I'm not binding back to the Database.
Actual Code (Added by Request)
This is the Property in my Composite Control that I'm trying to bind to:
Public Property DateTimeOffset As DateTimeOffset?
Get
Return CType(ViewState("DTO"), DateTimeOffset?)
End Get
Set(value As DateTimeOffset?)
ViewState("DTO") = value
End Set
End Property
Heres the markup for the Binding. The Control is in the EditItemTemplate of a FormView which is bound to a SQL DataSource returning a field called [dtoMldRejOn] with an optional DateTimeOffset value.
<APS:DateTimeOffsetControl runat="server" id="dtocMldRejOn" TextBoxCssClass="inputdatetime" ValidationGroup="vw1" FieldName="<%$ Resources: Resource, rxgFrom %>" DateTimeOffset='<%# Bind("dtoMldRejOn") %>' WindowsTimeZoneID="<%# me.WindowsTimeZoneID %>" IsRequired="false" />
As you can see, my Composite control is for handling DateTimeOffset values. It all works great unless the DateTimeOffset field [dtoMldRejOn] from the database is NULL, then I get the exception.
I have never created bindable controls before, but I would like to make suggestion. How about setting your DateTimeOffset property to be of type Object. That way, the property will accept any data types including DBNull.
And once inside the Set code, check if the value passed is DBNull.Value. If so, create a new empty DataTimeOffset? object and save it in the ViewState.
If non DBNull values, throw error if it cannot be be converted to datetime.
I didn't try this though so I don't know if this will work or not.
################ UPDATED ANSWER ################
My suggestion is, you create 2 properties as follows:
Public Property DateTimeOffset() As DateTimeOffset?
Get
Return DirectCast(ViewState("DTO"), DateTimeOffset?)
End Get
Set(ByVal Value As DateTimeOffset?)
ViewState("DTO") = Value
End Set
End Property
<Bindable(True, BindingDirection.TwoWay)>
Public Property DbDateTimeOffset As Object
Get
Return Me.DateTimeOffset
End Get
Set(value As Object)
If IsDBNull(value) OrElse value Is Nothing Then
Me.DateTimeOffset = New DateTimeOffset?
Else
Me.DateTimeOffset = DirectCast(value, DateTimeOffset?)
End If
End Set
End Property
So in your markup, the binding will be to the DbDateTimeOffset property:
DbDateTimeOffset='<%# Bind("myDateTimeOffsetField") %>'
While in code behind, you can use the other property to read the property without having to cast.
Based on this post,
I think you just need to mark your property with the Bindable attribute:
<System.ComponentModel.Bindable(True)> _
Public Property DateTimeOffset As DateTimeOffset?
The problem is that DbNull is different from Nothing and you must explicitly write that somewhere in your code. My first idea here was to use the binding events to add the value. So if you keep you code like this:
DateTimeOffset='<%# iif(IsDbNull(Eval("myDateTimeOffsetField")), Nothing, Eval("myDateTimeOffsetField")) %>'
You can manually add the DateTimeOffset parameter in the Updating events before the binding proceeds (I can update the answer later with more details on this if you want)
Anyway, after reading your code more carefully I thought that maybe the CType isn't casting correctly. Have you tried replacing your Get with something like this?
Get
Return If(IsDbNull(ViewState("DTO")), Nothing, CType(ViewState("DTO"), DateTimeOffset?))
End Get
Your code with iif ... works for me. I have created a testing control and a page version with code behind pages ( I have tested code behind version too but this one is easier to publish). I have VS2010 target framework is 4.0.
First the control(TstNullableCtrl.ascx):
<%# Control Language="vb" AutoEventWireup="false" %>
<script runat="server">
Public Property DateTimeOffset As DateTimeOffset?
</script>
<div ID="Label1" runat="server" >
<%= If(DateTimeOffset.HasValue, DateTimeOffset.ToString, "Empty")%>
</div>
and the page - a table with two rows and two columns bound to datagrid (TstNullablePage.aspx):
<%# Page Language="vb" AutoEventWireup="false" %>
<%# Import Namespace="System.Data"%>
<%# Register src="TstNullableCtrl.ascx" tagname="TstNullableCtrl" tagprefix="uc1" %>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim tbl As New DataTable
tbl.Columns.Add(New DataColumn("id", GetType(Integer)) With {.AutoIncrement = True})
tbl.Columns.Add(New DataColumn("myDateTimeOffsetField", GetType(DateTimeOffset)))
Dim row As DataRow
row = tbl.NewRow : row("myDateTimeOffsetField") = DateTimeOffset.Now
tbl.Rows.Add(row)
row = tbl.NewRow : row("myDateTimeOffsetField") = DBNull.Value
tbl.Rows.Add(row)
tstgrd.DataSource = tbl : tstgrd.DataBind()
End Sub
</script>
<html>
<body>
<form id="form1" runat="server">
<asp:datagrid ID="tstgrd" runat="server">
<Columns>
<asp:TemplateColumn HeaderText="Offset">
<itemtemplate>
<uc1:TstNullableCtrl ID="WithNullableDate1" runat="server"
DateTimeOffset='<%# iif(IsDbNull(Eval("myDateTimeOffsetField")), Nothing, Eval("myDateTimeOffsetField")) %>' />
</itemtemplate>
</asp:TemplateColumn>
</Columns>
</asp:datagrid>
</form>
</body>
</html>
And expected result (a value when there is and 'Empty' when is null)
Edit
However I think that to "avoid complication" best solution is as follows:
Public _DateTimeOffset As Object
Public Property DateTimeOffset As Object
Get
If IsDBnull(_DateTimeOffset) then Return Nothing
Return Ctype(_DateTimeOffset, DateTimeOffset?)
End Get
Set(value As Object)
_DateTimeOffset = value
End Set
End Property
I know this question have been already answered I just would like to document my solution which is in between those two answers as I have came across this today:
Private _AssetId As Object
<Bindable(True, BindingDirection.TwoWay)>
Public Property AssetId() As Object
Get
If _AssetId Is Nothing Then
Return Nothing
Else
Return CType(_AssetId, Integer)
End If
End Get
Set(ByVal value As Object)
If value Is Nothing OrElse IsDBNull(value) OrElse CType(value, String) = "" Then
_AssetId = Nothing
Else
_AssetId = CType(value, Integer)
End If
End Set
End Property

Asp.net VB Test value in GridView

I have found heaps of solutions for this in C# but when you are dealing with FindControls and trying to pull a value out of the GridView the C# doesn't help and the translated code doesn't work.
I have this gridview:
<asp:GridView ID="WIPListGrid" runat="server" DataSourceID="WIPDataSource"
CssClass="site" AutoGenerateColumns="False"
Width="95%" DataKeyNames="Masterid_Action" onrowdatabound="WIPListGrid_RowDataBound">
<Columns>
<asp:BoundField DataField="Action Due Date" HeaderText="Action Due Date"
SortExpression="Action Due Date" />
</Columns>
</asp:GridView>
and I have this in vb:
Protected Sub WIPListGrid_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles WIPListGrid.RowDataBound
Dim DueDate As Label = DirectCast(e.Row.FindControl("Action Due Date"), Label)
'do what ever you want to do here using the value of your label
MsgBox("Due Date = " & DirectCast(e.Row.FindControl("Action Due Date"), Label))
End Sub
Error message is Operator & is not defined for types 'String' and 'System.Web.UI.WebControls.Label'
This is a remedial example of what I ~really~ want to do. Above I just want to display what is contained in DueDate to see what format it is in so I can test it against other values. but it won't work. It appears the the contents of Action Due Date is not a string... so, what am I missing?
I have tried to set the value equal to a string but got the same problem, the Label isn't a string...
How do I find out what's in there in order to evaluate it?
17/01/2013 edit: Keeping this active as I still do not have my issue resolved.
18/01/2013 edit:
vb.net code is now
Protected Sub WIPListGrid_ROWDataBound(sender as Object,
e As System.Web.UI.Webcontrols.GridViewRowEventArgs) Handles WIPListGrid.RowDataBound
Dim DueDate As Label = DirectCast(e.Row.FindControl("Action Due Date"), Label)
'do what ever you want to do here using the value of your label
MsgBox("Due Date = " & DueDate.Text)
End Sub
But now I get an error that the Object isn't instantiated and its pointing to the msgbox line in the code. I thought that I instantiated it when I dim it as a Label...
The official error is:
"Object reference not set to an instance of an object."
the troubleshooting tips say to
1) Use the "new" keyword to create an object instance
2) Check to determine if the object is null before calling the method
I tried the "new" option and got an error that says the variable has already been declared.
So now I want to check to determine if the object is null and can't figure out how.
I've tried testing: DirectCast(e.Row.FindControl("action due date"), Label) <> ""
but got an error: Overload resolution failed because no accessible '<>' can be called with these arguments.
How do I test to see if the object is null?
The value shouldn't be null (the database doesn't allow it to be null), BUT this could be the crux of my issue...
Any help?
When working with controls, you have to point out that you want that value inside your control.
In your case, you're just going for the label-control itself (not the text inside).
For example:
Dim myControl As Label = DirectCast(e.Row.FindControl("myControl"), Label)
MsgBox("MyText = " & myControl.Text)
Hope this helps.
The problem is you are using a BoundField so there is no control to find. Change it to a templatefield and this will work.
<asp:GridView ID="WIPListGrid" runat="server" DataSourceID="WIPDataSource"
CssClass="site" AutoGenerateColumns="False"
Width="95%" DataKeyNames="Masterid_Action" onrowdatabound="WIPListGrid_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Action Due Date">
<ItemTemplate>
<asp:Label ID="lblActionDueDate" runat="server" Text='<%# Bind("[Action Due Date]") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
For Your Row DataBound Event use
Dim DueDateLabel As Label = DirectCast(e.Row.FindControl("lblActionDueDate"), Label)
'Check Label Exists
If DueDateLabel IsNot Nothing Then
Dim DueDateText As String = DueDateLabel.Text
MsgBox(String.Format("Due Date {0}", DueDateText))
End If

DataFormatString from a dataset, by code

I have selected a bunch of data from my access database which one of the fields is a DateTime field.
I'm trying to show it formated in a GridView but when I try:
dtlJob.DataSource = genericDataSet
dtlJob.Fields(2).DataFormatString = "{0:d}"
dtlJob.DataBind()
I get this error on line 2
Error 2 'DataFormatString' is not a member of 'System.Web.UI.WebControls.DataControlField'.
How do I format my data?
EDIT
This is my DetailsGridView I'm trying t o show off
<asp:DetailsView ID="dtlJob" runat="server" Height="50px" Width="125px">
</asp:DetailsView>
it has nothing but its tags for I'm fetching every data by code from a database. But I want to format the Data Date Field which is appearing like this no more which data it has
You have to create a BoundField like the code below.
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="false" Height="50px" Width="125px">
<Fields>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="Age" HeaderText="Age" />
<asp:BoundField DataField="Birth" HeaderText="Birth" DataFormatString="{0:d}" />
</Fields>
</asp:DetailsView>
I hope that helped.
Vicente
The fields property is readonly, so you can't modify it except in constructor.
Please notice that I have not tested this solution, bt this is what I think you have to do.
So you have to create a new class that inherits from details view and shadows the Fields property, using its own private _fields field:
Imports System.Web.UI.WebControls
Public Class CustomDetailsView
Inherits DetailsView
Private _fields As System.Web.UI.WebControls.DataControlFieldCollection
Public Shadows Property Fields As System.Web.UI.WebControls.DataControlFieldCollection
Get
Return _fields
End Get
Set(ByVal value As System.Web.UI.WebControls.DataControlFieldCollection)
_fields = value
End Set
End Property
End Class
Then you have the following code, creating a CustomDetailsView object, telling it that its datasource is the dataset, formatting the second column field, and giving all hese information to your detaisview on the web form, before binding the data.
Dim myDetailsView = New CustomDetailsView
myDetailsView.DataSource = genericDataSet
CType(myDetailsView.Fields(1), BoundField).DataFormatString = "{0:d}"
dtlJob = myDetailsView
dtlJob.DataBind()
BoundField's base type is DataControlField, so you can write the CType line.
I can't test this right now, please do it and post feedback. If it doesn't work, it could be a beginning of answer.
Greetings
Here is an another solution (still not tested). Here you still make a new class inheriting DetailsView, and you access the fields variable in the constructor:
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Public Class _CustomDetailsView
Inherits DetailsView
Public Sub New(ByVal Columns As List(Of String))
For Each item As String In Columns
Dim bfield As New BoundField
If Not String.IsNullOrWhiteSpace(item) Then
bfield.DataFormatString = item
Else
bfield.DataFormatString = ""
End If
Me.Fields.Add(bfield)
Next
End Sub
End Class
Then, you create a list of string containing the wanted formatting for each column. Then you create your _CustomDetailsView by passing this list of string in the constructor.
Next you assign your DtlJob the _CustomDetailsView object, and finally you provide the datasource and proceed the databinding:
Dim DataFieldStyles = New List(Of String)
' First column: Default style
' Second column: Date format
' Third : Currency Format
' Fourth : Default style
DataFieldStyles.AddRange(New String() {"", "{0:d}", "{0:c}", ""})
Dim My_DetailsView As _CustomDetailsView = New _CustomDetailsView(DataFieldStyles)
dtlJob = My_DetailsView
dtlJob.DataSource = genericDataSet
dtlJob.DataBind()
Same remark as for my other answer, I can't test this, so try it and please give feedback.
Greetings

vbCrLf in Multiline TextBox shows up only when .Trim() is called

I have an ASP TextBox with TextMode set to MultiLine. I'm having problems with preserving the vbCrLf characters when a user tries to put line breaks into the text. When a button on the page is pressed, I'm taking the text from the control, trimming it using String.Trim, and assigning that value to a String property on an object (which, in turn assigns it to a private internal String variable on the object). The object then takes the value from the private internal variable and throws it into the database using a stored procedure call (the SP parameter it is put into is an nvarchar(4000)).
ASPX Page:
<asp:UpdatePanel ID="UpdatePanel2" runat="server" RenderMode="Inline" UpdateMode="Conditional"
ChildrenAsTriggers="true">
<ContentTemplate>
<!-- some other controls and things -->
<asp:TextBox TextMode="MultiLine" runat="server" ID="txtComments" Width="100%" Height="60px" CssClass="TDTextArea" Style="border: 0px;" MaxLength="2000" />
<!-- some other controls and things -->
</ContentTemplate>
</asp:UpdatePanel>
code behind:
ProjectRequest.StatusComments = txtComments.Text.Trim
object property:
Protected mStatusComments As String = String.Empty
Property StatusComments() As String
Get
Return mStatusComments.Trim
End Get
Set(ByVal Value As String)
mStatusComments = Value
End Set
End Property
stored proc call:
Common.RunSP(mDBConnStr, "ProjectStatusUpdate", _
Common.MP("#UID", SqlDbType.NVarChar, 40, mUID), _
Common.MP("#ProjID", SqlDbType.VarChar, 40, mID), _
Common.MP("#StatusID", SqlDbType.Int, 8, mStatusID), _
Common.MP("#Comments", SqlDbType.NVarChar, 4000, mStatusComments), _
Common.MP("#PCTComp", SqlDbType.Int, 4, 0), _
Common.MP("#Type", Common.TDSqlDbType.TinyInt, 1, EntryType))
Here's the strangest part. When I debug the code, if I type
"test
test"
(without the quotes) into the comments text box, then click the save button and use the immediate window to view the variable values as I step through, here is what I get:
?txtComments.Text
"test test"
?txtComments.Text.Trim
"test
test"
?txtComments.Text(4)
"
"c
?txtComments.Text.Trim()(4)
"
"c
Anyone have a clue as to what's going on here?
There are two problems at bay here. First, the immediate window in VB is converting the non-printable character to a space so you cannot see it. In C#, it will show the character using its replacement escape code (e.g. \n or \r\n), but VB does not. Second, VB sees the break as a line-feed only (vbLf) not a carriage-return+line-feed (vbCrLf). Thus, if you do the following in break mode in the immediate window you will see what I mean (assuming you type test, hit Enter, test in the comments box):
?txtComments.Text.Substring(4,1) = vbLf
True
May be, you should use Environment.NewLine constant to get replaced with the vbCrLf

Resources