Sorting List(Of MaskedTextBox) - vb.net

The list Private msklistclass1 As New List(Of MaskedTextBox) contains following MaskedTextBox controls after executing the following code
For Each ctrl As Control In Me.pnlclass11.Controls
If TypeOf ctrl Is MaskedTextBox Then
msklistclass1.Add(ctrl)
End If
Next
seat112
seat212
seat312
seat412
seat512
seat612
seat122
seat222
seat322
seat422
seat522
seat622
but they aren't in the order I have shown above I suppose. When I try to assign values to these controls in a sequential manner they don't get assigned in an order.
I tried the following code
For i = 0 To 11 Step 1
msklistclass1(i).Text = rno312(i)
Next
The assignment I expect is
seat112 1138M0321
seat212 1138M0322
seat312 1138M0323
seat412 1138M0324
seat512 1138M0325
seat612 1138M0326
But they aren't getting assigned in this order
Is there a possibility to sort the list msklistclass1
This line gives me the following output msklistclass1.Sort(Function(x, y) x.Name.CompareTo(y.Name))
seat111 1138M0321 seat121 1138M0321
seat211 1138M0323 seat221 1138M0324
seat311 1138M0325 seat321 1138M0326
seat411 1138M0326 seat421 1138M0327
seat511 1138M0328 seat521 1138M0329
seat611 1138M0330 seat621 1138M0331
but I want
seat111 1138M0321 seat121 1138M0327
seat211 1138M0322 seat221 1138M0328
seat311 1138M0323 seat321 1138M0329
seat411 1138M0324 seat421 1138M0330
seat511 1138M0325 seat521 1138M0331
seat611 1138M0326 seat621 1138M0332

Using LINQ, you can do this:
Dim listOrdered = From m In msklistclass1 Order By m.Text
Or if you cannot use LINQ or do not want to, then do this:
msklistclass1.Sort(Function(x, y) x.Name.CompareTo(y.Text))
Note: If you want to sort by a different property of the MaskedTextBox, then just change Text to whatever the property name is, like Name for instance.

Related

Json to datatable with proper column data get from json

My JSON data looks as shown below. Sometimes it's changed the Field Name Position. How to store this data into a Datatable and must be in proper column. Suggest any solution for VB.Net
<string xmlns="http://tecogis.com/">[
{
"REPORT NUMBER":"LG534248650",
"REPORT CITY DATE":"June 22, 2022",
"DESCRIPTION":"LABORATORY GROWN DIAMOND",
"SHAPE AND CUT":"ROUND BRILLIANT",
"CARAT WEIGHT":"1.07 Carat",
"COLOR GRADE":"D",
"CLARITY GRADE":"SI 2",
"CUT GRADE":"VERY GOOD",
"POLISH":"EXCELLENT",
"SYMMETRY":"EXCELLENT",
"Measurements":"6.41 - 6.44 x 4.10 mm",
"Table Size":"57%",
"Crown Height":"15.5% - 35.4°",
"Pavilion Depth":"43.5% - 41.1°",
"Girdle Thickness":"MEDIUM TO SLIGHTLY THICK (FACETED)",
"Culet":"POINTED",
"Total Depth":"63.9%",
"FLUORESCENCE":"NONE",
"COMMENTS":"As Grown - No indication of post-growth treatment\r\nThis Laboratory Grown Diamond was created by High Pressure High Temperature (HPHT) growth process\r\nType II\r\n",
"Inscription(s)":"LABGROWN IGI LG534248650\u003cbr\u003e",
"REPORT_SUF":"LEGAL",
"PDF_FLAG":"Y",
"REPORT1_PDF":"FDR534248650.pdf"
}
]</string>
This is the missing piece you need. Note that it's from my own project so just adjust accordingly for your situation.
Before this, you just need to create a List of your custom type, populate it from your JSON (see Hursey's answer) and reference it instead of BlogList from my code.
This code will then transfer the data from your List into a DataTable which is the DataSource for the DataGridView.
'Declare a DataTable:
Private BlogTable As New DataTable
'Through code, modify a DataGridView instance on your form and clear things:
dgvBlogs.Columns.Clear()
dgvBlogs.DataSource = Nothing
'Set up our columns in the DataTable:
BlogTable.Columns.Add("blogname")
BlogTable.Columns.Add("username")
BlogTable.Columns.Add("password")
dgvBlogs.AutoGenerateColumns = True
dgvBlogs.DataSource = BlogTable
'Put data from JSON into the DataSource:
BlogTable.Rows.Clear()
For Each item As BlogRecord In BlogList
Dim row As DataRow = BlogTable.NewRow()
row("blogname") = item.BlogName
row("username") = item.Username
row("password") = item.Password
BlogTable.Rows.Add(row)
Next
So, conceptually, it's like this:
JSON -> List Of(Your Class) -> DataTable -> DataGridView.DataSource
You turn your JSON into a list of whatever custom item type you want to call it. Then you populate a DataTable from that. And you be sure that your DataGridView.DataSource property is set to your DataTable.
This works for me. The only thing to add is double-check the AutoGenerateColumns because for some reason in my code first I set it to True and then later to False. I'm sure that was just me experimenting and I never cleaned it up.

Setting a variable to linq query with no results

I have a table that holds links to websites about particular theaters. I want to retrieve the first link for a given theater. My code to set the variable:
Dim link As String = TheaterLinks.Where(Function(x) x.TheaterID = TheaterID).FirstOrDefault().Link
If there are no results (some theaters won't have any links), then I get:
Object reference not set to an instance of an object.
How do I do this? I tried:
Dim link As String = Links.Where(Function(x) x.TheaterID = TheaterID.DefaultIfEmpty().First().Link
But I can't figure out what to put inside DefaultIfEmpty(). I tried DefaultIfEmpty("") and DefaultIfEmpty(blankstringvariable) but then I get:
Value of type 'String' cannot be converted to type 'TheaterLink'.
The problem is that FirstOrDefault() is allowed to return null, in which case accessing Link property would throw an exception.
If you use VB.NET 14, add question mark for automatic null checking:
Dim link As String = TheaterLinks.Where(Function(x) x.TheaterID = TheaterID).FirstOrDefault()?.Link
(see ?.Link instead of .Link)
Otherwise, do it in two stages: first, get the object using FirstOrDefault, then null-check it manually with an If statement.
For my original example, I just had to add a question mark:
Dim link As String = Links.Where(Function(x) x.ID = id).FirstOrDefault()?.Link
I tried doing this in my model and got a "Nullable object must have a value" error, so I did the two-stage approach:
Dim eventDate = Events.Where(Function(x) x.ID = id).FirstOrDefault()?.EventDate
If eventDate.HasValue Then
'some code
Else
'some code
End If

Calling a function within Entity Framework Select

A property from my object (oJobs) is as follows:
Private _brandlist As List(Of DAL.Brand)
Public Property PostBrandList() As List(Of DAL.Brand)
Get
Return _brandlist
End Get
Set(ByVal value As List(Of DAL.Brand))
_brandlist = value
End Set
End Property
In the database, the brand list is stored as a string separated by comma e.g. the column 'brands' can be a string '3,45,2' where each number represents an id of a brand stored in another table.
my select query is as below:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = 'problem is here'
}
Since j.BrandList will return a string, I will need to split that string and for each number, run another query to finally return and assign a List(Of DAL.Brand) into .PostBrandList
For those who might ask "what have you tried?",
I have run the query, then did a for each to add the list of brands later - succeeded but not optimal
Coded a function that takes the list as a parameter and returns a separate list of objects - very silly.
Also, I am not allowed to normalize the DB :(
Not tested and might need some tweaking but heres one idea. you will also need to change your property to an IEnumerable rather than List. Because the second linq query is embedded within the first, I believe it should execute it all as one query, but you should check it to make sure.
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = From b In db.Brands Where j.Brands = b.ID Or j.Brands.StartsWith(b.ID & ",") Or j.Brands.EndsWith("," & b.ID) Or j.Brands.Contains("," & b.ID & ",") Select b
}
In c# you can use
.Select(x=>new {x.BrandList})
.ToList() //Materialize first before calling function
.Select(x=> new oJobs{
PostBrandList =
db.Brands.Where(z=>
x.BrandList
.Split(',')
.Select(y=>int.Parse(y.Trim()))
.Contains(z.Id))
.ToList()
});
Note that you must materialize entity first before calling String.Split
I don't know how to translate that to VB.NET.
Of course it will cause SELECT n+1 problem because you can't use join.
If you can't normalize table, my other suggestion is to create indexed view (sql server), so you can use join and improve performance.
Indexed view https://msdn.microsoft.com/en-us/library/ms191432.aspx
You could try it with the Let statement:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
/* li in the LINQ Statement represents one string value from the BrandList list */
Let postBrandElemsList = j.BrandList.Split(',').Select(Function(li) New DAL.Brand With { ... /* Field initializatione of the Class DAL.Brand here */ }
Select New oJobs With
{
.PostBrandList = postBrandElemsList
}
I'm sorry for the probably bad VB.NET syntax, you should check this when implementing it in your code.
Maybe you would just want to use the Split function on the column brands into an array and iterate through the result, using the Find function to retrieve the brand objects?

How to disable validating row when it loses focus in Datagridview

I have a datagridview, and I would like to allow the end user to type whateever he wants in the rows and the validation will be done later programmatically.
For example
Column1 : AllowDBNull = true
The user will still be able skip the cell related to Column1 and move to another row (may be to fill it later)
And the validation will be performed once he clicks ValidateButton.
I have been looking to :
DataGridView.CausesValidation = False
But that was unsuccessful.
I was trying also
DataSourceUpdateMode = DataSourceUpdateMode.Never
but couldn't apply this property to DataGridView.Datasource
Here is a bit of my code
'CreateMasterDataTable and CreateDetailDataTable are two functions that return two datatables
Master_DT = CreateMasterDataTable()
Detail_DT = CreateDetailDataTable()
DataSet.Tables.Add(Master_DT)
DataSet.Tables.Add(Detail_DT)
DataSet.Relations.Add("Relation", Master_DT.Columns("City"), Detail_DT.Columns("City"))
Master_BindingSource.DataSource = DataSet
Master_BindingSource.DataMember = Master_DT.TableName
Details_BindingSource.DataSource = Master_BindingSource
Details_BindingSource.DataMember = "Relation"
DataGridView.DataSource = Details_BindingSource
Does anyone have an idea on how to disable the row validation once it loses focus please ?
Thanks

Matlab's arrayfun for uniform output of class objects

I need to build an array of objects of class ID using arrayfun:
% ID.m
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
obj.id = id;
end
end
end
But get an error:
>> ids = 1:5;
>> s = arrayfun(#(id) ID(id), ids)
??? Error using ==> arrayfun
ID output type is not currently implemented.
I can build it alternatively in a loop:
s = [];
for k = 1 : length(ids)
s = cat(1, s, ID(ids(k)));
end
but what is wrong with this usage of arrayfun?
Edit (clarification of the question): The question is not how to workaround the problem (there are several solutions), but why the simple syntax s = arrayfun(#(id) ID(id), ids); doesn't work. Thanks.
Perhaps the easiest is to use cellfun, or force arrayfun to return a cell array by setting the 'UniformOutput' option. Then you can convert this cell array to an array of obects (same as using cat above).
s = arrayfun(#(x) ID(x), ids, 'UniformOutput', false);
s = [s{:}];
You are asking arrayfun to do something it isn't built to do.
The output from arrayfun must be:
scalar values (numeric, logical, character, or structure) or cell
arrays.
Objects don't count as any of the scalar types, which is why the "workarounds" all involve using a cell array as the output. One thing to try is using cell2mat to convert the output to your desired form; it can be done in one line. (I haven't tested it though.)
s = cell2mat(arrayfun(#(id) ID(id), ids,'UniformOutput',false));
This is how I would create an array of objects:
s = ID.empty(0,5);
for i=5:-1:1
s(i) = ID(i);
end
It is always a good idea to provide a "default constructor" with no arguments, or at least use default values:
classdef ID < handle
properties
id
end
methods
function obj = ID(id)
if nargin<1, id = 0; end
obj.id = id;
end
end
end