I have a view model whose values are sent as a list from the view for edit four input boxs ...
public class UpdatePollViewModel
{
public List<string> Answer { get; set; }
}
In my service, I got the same values from the database via Id:
public bool UpdatePoll(Guid id, UpdatePollViewModel viewModel)
{
var polloption = _context.PollOptions.Where(p => p.PollId == Id).ToList();
}
I used this but it does not make sense because it repeats a lot!!!
foreach (string item in viewModel.Answer)
{
foreach (var item2 in polloption)
{
item2.Answer = item;
_context.SaveChanges();
}
}
What is the best way to handle this?
I'm going to assume that the magic number is 4.
There are 4 input boxes that are used to populate the view model list with 4 answers in the same order as the existing 4 answers that are retrieved from the database and you want to map the 4 inputs to the 4 records from the database.
var polloption = _context.PollOptions.Where(p => p.PollId == Id).ToList();
for (int i = 1; i <= 4; i++)
{
polloption[i-1].Answer = viewModel.Answer[i-1];
}
_context.SaveChanges();
Related
How to combine Id from the list I get from file /test.json and id from list ourOrders[i].id?
Or if there is another way?
private RegionModel FilterByOurOrders(RegionModel region, List<OurOrderModel> ourOrders, MarketSettings market, bool byOurOrders)
{
var result = new RegionModel
{
updatedTs = region.updatedTs,
orders = new List<OrderModel>(region.orders.Count)
};
var json = File.ReadAllText("/test.json");
var otherBotOrders = JsonSerializer.Deserialize<OrdersTimesModel>(json);
OtherBotOrders = new Dictionary<string, OrderTimesInfoModel>();
foreach (var otherBotOrder in otherBotOrders.OrdersTimesInfo)
{
//OtherBotOrders.Add(otherBotOrder.Id, otherBotOrder);
BotController.WriteLine($"{otherBotOrder.Id}"); //Output ID orders to the console works
}
foreach (var order in region.orders)
{
if (ConvertToDecimal(order.price) < 1 || !byOurOrders)
{
int i = 0;
var isOurOrder = false;
while (i < ourOrders.Count && !isOurOrder)
{
if (ourOrders[i].id.Equals(order.id, StringComparison.InvariantCultureIgnoreCase))
{
isOurOrder = true;
}
++i;
}
if (!isOurOrder)
{
result.orders.Add(order);
}
}
}
return result;
}
OrdersTimesModel Looks like that:
public class OrdersTimesModel
{
public List<OrderTimesInfoModel> OrdersTimesInfo { get; set; }
}
test.json:
{"OrdersTimesInfo":[{"Id":"1"},{"Id":"2"}]}
Added:
I'll try to clarify the question:
There are three lists with ID:
First (all orders): region.orders, as order.id
Second (our orders): ourOrders, as ourOrders[i].id in a while loop
Third (our orders 2): from the /test.json file, as an array {"Orders":[{"Id":"12345..."...},{"Id":"12345..." ...}...]}
There is a foreach in which there is a while, where the First (all orders) list and the Second (our orders) list are compared. If the id's match, then these are our orders: isOurOrder = true;
Accordingly, those orders that isOurOrder = false; will be added to the result: result.orders.Add(order)
I need:
So that if (ourOrders[i].id.Equals(order.id, StringComparison.InvariantCultureIgnoreCase)) would include more Id's from the Third (our orders 2) list.
Or any other way to do it?
You should be able to completely avoid writing loops if you use LINQ (there will be loops running in the background, but it's way easier to read)
You can access some documentation here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/introduction-to-linq-queries
and you have some pretty cool extension methods for arrays: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable?view=net-6.0 (these are great to get your code easy to read)
Solution
unsing System.Linq;
private RegionModel FilterByOurOrders(RegionModel region, List<OurOrderModel> ourOrders, MarketSettings market, bool byOurOrders)
{
var result = new RegionModel
{
updatedTs = region.updatedTs,
orders = new List<OrderModel>(region.orders.Count)
};
var json = File.ReadAllText("/test.json");
var otherBotOrders = JsonSerializer.Deserialize<OrdersTimesModel>(json);
// This line should get you an array containing
// JUST the ids in the JSON file
var idsFromJsonFile = otherBotOrders.Select(x => x.Id);
// Here you'll get an array with the ids for your orders
var idsFromOurOrders = ourOrders.Select(x => x.id);
// Union will only take unique values,
// so you avoid repetition.
var mergedArrays = idsFromJsonFile.Union(idsFromOurOrders);
// Now we just need to query the region orders
// We'll get every element that has an id contained in the arrays we created earlier
var filteredRegionOrders = region.orders.Where(x => !mergedArrays.Contains(x.id));
result.orders.AddRange(filteredRegionOrders );
return result;
}
You can add conditions to any of those actions (like checking for order price or the boolean flag you get as a parameter), and of course you can do it without assigning so many variables, I did it that way just to make it easier to explain.
I've visited every search result I could find but I'm stuck.
I'm working on a "dvd store" website using ASP.Net MVC 5, and I'm having some difficulty with inserting MultiSelectList values into the database. The database structure has a many-to-many table which stores the movie Id, genre Id, and a primary key. There's also a movie table with fields like movie title, cost, image path, director, rating, etc.
My insert logic works for putting data into the movies table, but I have a multiselectlist in my Create view which is populated from a list of movie genres in the database. When I select one list item, the ID inserts into the moviegenre table just fine. When I select more than one, only one ID is inserted. I'd like to insert a new row for each selection, with the movie ID and the genre ID (i.e. if 3 genres are selected, create 3 new rows with the same movie id but different genre id's for each row).
How can I iterate through the posted MultiSelectList data and insert a new row for each value?
This is the code in my View:
#Html.ListBoxFor(r => r.CMovie.GenreId, new MultiSelectList(Model.CGenreList, "Id", "Description"), new { #class = "form-control" })
My Controller:
[HttpPost]
public ActionResult Create(MovieGenresDirectorsRatings mgdr) // The ViewModel
{
try
{
mgdr.CMovie.Insert();
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
return View(mgdr);
}
}
The ViewModel:
public class MovieGenresDirectorsRatings
{
public IEnumerable<int> GenreId { get; set; }
public CGenreList CGenreList { get; set; }
public CDirectorList CDirectorList{ get; set; }
public CFormatList CFormatList { get; set; }
public CRatingList CRatingList { get; set; }
public CGenre CGenre { get; set; }
public CMovie CMovie { get; set; }
}
And my Insert logic in the Model:
public void Insert()
{
using (myEntities dc = new myEntities())
{
try
{
tblMovie movie = new tblMovie();
// Add movie to tblMovie
movie.Id = 1;
if (dc.tblMovies.Any())
movie.Id = dc.tblMovies.Max(p => p.Id) + 1;
this.Id = movie.Id;
movie.Title = this.Title;
movie.Description = this.Description;
movie.ImagePath = this.ImagePath;
movie.Cost = this.Cost;
movie.RatingId = this.RatingId;
movie.FormatId = this.FormatId;
movie.DirectorId = this.DirectorId;
try
{
tblMovieGenre genre = new tblMovieGenre();
genre.Id = 1;
if (dc.tblMovieGenres.Any())
genre.Id = dc.tblMovieGenres.Max(p => p.Id) + 1;
// THIS IS THE PART that I'm struggling with.
// I think the data is there, I'm just not sure how to access it
foreach (var GenreId in GenreId) // This line is probably wrong, but I'm not sure how to access the data
{
genre.GenreId = this.GenreId.FirstOrDefault();
genre.MovieId = movie.Id;
dc.tblMovieGenres.Add(genre);
}
}
catch (Exception ex)
{
throw ex;
}
dc.tblMovies.Add(movie);
// Commit changes
dc.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
}
}
I've tried foreach loops and for loops and I can't get it to work. What am I doing wrong?
Edit #1: After making a few changes, here is my (current and non-working) complete Insert logic in the CMovie class. When I only choose one "genre" from the MultiSelectList, it works fine and inserts into both tables properly. However, when I select two or more "genres" from the MultiSelectList, I get a "Value cannot be null, parameter name: items" error.
public void Insert()
{
using (dbEntities2 oDc = new dbEntities2())
{
try
{
tblMovie movie = new tblMovie();
// Add movie to tblMovie
movie.Id = 1;
if (oDc.tblMovies.Any()) // If table is not empty
movie.Id = oDc.tblMovies.Max(p => p.Id) + 1;
this.Id = movie.Id;
movie.Title = this.Title;
movie.Description = this.Description;
movie.ImagePath = this.ImagePath;
movie.Cost = this.Cost;
movie.RatingId = this.RatingId;
movie.FormatId = this.FormatId;
movie.DirectorId = this.DirectorId;
try
{
foreach (var GenreId in GenreIds)
{
tblMovieGenre genre = new tblMovieGenre();
genre.Id = 1;
if (oDc.tblMovieGenres.Any())
{
genre.Id = oDc.tblMovieGenres.Max(p => p.Id) + 1; // genre.Id is set to the highest id in the table, +1
}
genre.Id = this.Id;
genre.GenreId = GenreId;
genre.MovieId = movie.Id;
oDc.tblMovieGenres.Add(genre);
}
}
catch (Exception ex)
{
throw ex;
}
oDc.tblMovies.Add(movie);
// Commit changes
oDc.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
}
}
}`
Edit 2: I've found a solution to the problem. Hopefully this helps someone else having the same issue. I changed the create to use a dropdownlist instead of a multiselectlist, and modified the edit method to allow for updating of multiple genres.
Inside the CMovie Model, I created two new methods, AddGenre and DeleteGenre. In the controller, I added four new IEnumerable<int> variables: oldGenreIds, newGenreIds, adds, and deletes.
I then made a list from the IEnumerable deletes and adds:
IEnumerable<int> deletes = oldGenreIds.Except(newGenreIds);
IEnumerable<int> adds = newGenreIds.Except(oldGenreIds);
deletes.ToList().Foreach(a => mgdr.CMovie.DeleteGenre(id, a));
adds.ToList().Foreach(a => mgdr.CMovie.AddGenre(id, a));
The update method is then called, which sets the changed values (including the movie title, description, image path, etc):
mgdr.CMovie.Update();
By moving the ForEach logic into the controller, I was able to call the AddGenre method several times - which I wasn't able to do when calling it directly inside the Insert method.
Your post method should accept array rather than single object.
[HttpPost]
public ActionResult Create(MovieGenresDirectorsRatings[] mgdr) // The ViewModel
{
foreach(var genr in mgdr){
try
{
genr.CMovie.Insert(); //inserting each object received from view.
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
return View(mgdr);
}
}
}
The idea is receive all objects from view. Even if your view is posting all the items from multiselect list, you need array like structure in your controller to get data from view. Once you have that data in controller, you loop through all of them inserting one by one.
Here is the problem (an overlook actually):
tblMovieGenre genre = new tblMovieGenre();
// code...
foreach (var GenreId in GenreId)
{
genre.GenreId = this.GenreId.FirstOrDefault();
// code
dc.tblMovieGenres.Add(genre);
}
So see in the above code you create one tblMovieGenre and then in your loop you keep adding the same instance of tblMovieGenres over and over again. So essentially you add a single tblMovieGenres with values from the last iteration in your loop.
Fix
To fix the issue move the instantiation inside the loop:
foreach (var GenreId in GenreId)
{
tblMovieGenre genre = new tblMovieGenre();
// code...
dc.tblMovieGenres.Add(genre);
}
Other Suggestions
1
Hungarian notation is not encouraged in .NET so prefixing your database tables with tbl is not only a notation problem but makes your code harder to read, especially when you use an ORM. Therefore, if you remove the tbl from table names, your code will be:
MovieGenere instead of tblMovieGenre.
2
Also, if I look at one line of code and I can figure out the type of the object, I always use var instead. Like this:
tblMovieGenre genre = new tblMovieGenre();
var genre = new tblMovieGenre();
That is a personal preference (less typing).
But if I cannot figure the type from reading the single line, then I do not use var:
tblMovieGenre genre = GetMovie();
3
If you make your table primary key columns identity columns starting at 1, then you will not need such code:
movie.Id = 1;
if (dc.tblMovies.Any())
movie.Id = dc.tblMovies.Max(p => p.Id) + 1;
Whenever you create a new object in code, it will have an ID of 0 and when you add it to the db, EF will treat it like a new record and generate a new identity for it. This takes the responsibility of managing IDs away from you, which means less coding.
I have a list of records generated from a search query in my View. There's certain fields that can be edited and next step is do update those fields with one button/action.
The yellow fields are the ones that have been edited, while the white fields still match what is in the database table. Now when I click update all I first get the values of sellprice and casecost from the DB, then I get the values from the form. If the values match then move on, if the values from the form have been changed then update. I have datareader that reads the values from the table/database perfectly fine for each line of records on page.
NpgsqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
var prod = new ProductViewModel();
prod.q_guid = Guid.Parse(dr["q_guid"].ToString());
prod.q_sellprice = Convert.ToDecimal(dr["q_sellprice"]);
prod.q_casecost = Convert.ToDecimal(dr["q_casecost"]);
/*
At this point
Need to compare dr.Read q_sellprice and q_casecost
with changed values in the fields
if != then update for that record
*/
/*Lets assign previous values (values in db) to variables*/
var previousSellprice = prod.q_sellprice;
var previousCasecost = prod.q_casecost;
var thatId = prod.q_guid;
/*Lets get current values from form/list*/
var priceList = Request.Form["item.q_sellprice"];
var costList = Request.Form["item.q_casecost"];
/*eg*/
if (previousSellprice != currentSellprice || previousCasecost != currentCasecost)
{
//lets update record with new values from view
}
-> loop move on to next row in view
My DataReader while loop can get the value of each row no problemo. What I am trying to achieve when it gets the values of the first row from the db, then
I need to check what the current values in the form for that record are
if they are different then update for that current row
move on to next row in the view/on page
I have managed to get the array of values for these fields with these variables with the following code. This has the edited/changed fields from the list/form.
var priceList = Request.Form["item.q_sellprice"];
var costList = Request.Form["item.q_casecost"];
On my first run through the loop, I would like to get the values 10.00 and 8.50, do my check, update if necessary.. then move on the next row which will get 3.33 and 8.88, do my check, and update if necessary and so on for the rest of the records on that page.
So how can I loop through Request.Forms in the instance, and get my individual values for one record at a time?
cshtml on view for the fields is
#foreach (var item in Model)
{
<td>
€ #Html.EditorFor(modelItem => item.q_sellprice, new { name="q_sellprice" })
</td>
<td>
€ #Html.EditorFor(modelItem => item.q_casecost, new { name="q_casecost"})
</td>
Addition: Updating isnt the issue, getting the values of each record from the array while looping through the form fields is.
It is a long description of the problem - but from my understanding, your only problem is, that you want to have some data, which right now is two strings to be as List of operations (data) to perform? Is that correct?
If so - you can have such data in List using Zip method:
void Main()
{
string priceList = "1,2,3,4";
string costList = "2,3,4,5";
var prices = priceList.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries);
var costs = costList.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries);
var collectionToUpdate = prices.Zip(costs, (price, cost) => new PriceToUpdate(price, cost));
//do update in database with collectionToUpdate
}
public class PriceToUpdate
{
public PriceToUpdate(string oldPrice, string newPrice)
{
decimal priceTmp;
if (decimal.TryParse(oldPrice, out priceTmp))
{
OldPrice = priceTmp;
}
if (decimal.TryParse(newPrice, out priceTmp))
{
NewPrice = priceTmp;
}
}
public decimal OldPrice { get; set; }
public decimal NewPrice { get; set; }
}
My suggestion would be to re-organise your HTML a bit more and modify the method for getting the fields parsed out. What I have done in the past is include the Key Id (in your case the Guid) as part of the output. So the result in a basic view looks like:
If you notice the name attribute (and Id) are prefixed with the q_guid field. Here is my basic model.
public class ProductViewModelItems
{
public IList<ProductViewModel> items { get; set; } = new List<ProductViewModel>();
}
public class ProductViewModel
{
public Guid q_guid { get; set; }
public decimal q_sellprice { get; set; }
public decimal q_casecost { get; set; }
//other properties
}
And my controller just has a simple static model. Of course yours is built from your database.
static ProductViewModelItems viewModel = new ProductViewModelItems()
{
items = new[]
{
new ProductViewModel { q_casecost = 8.50M, q_sellprice = 10M, q_guid = Guid.NewGuid() },
new ProductViewModel { q_casecost = 8.88M, q_sellprice = 3.33M, q_guid = Guid.NewGuid() },
new ProductViewModel { q_casecost = 9.60M, q_sellprice = 3.00M, q_guid = Guid.NewGuid() },
new ProductViewModel { q_casecost = 9.00M, q_sellprice = 5.00M, q_guid = Guid.NewGuid() },
new ProductViewModel { q_casecost = 10M, q_sellprice = 2.99M, q_guid = Guid.NewGuid() },
}
};
[HttpGet]
public ActionResult Index()
{
//load your view model from database (note mine is just static)
return View(viewModel);
}
Now we construct our form so that we can pull it back in our post method. So I have chosen the format of {q_guid}_{field_name} as
q_casecost = {q_guid}_q_casecost
q_sellprice = {q_guid}_q_sellprice
The form construction now looks like.
#foreach (var item in Model.items)
{
<tr>
<td>
€ #Html.TextBoxFor(modelItem => item.q_sellprice, new { Name = string.Format("{0}_q_sellprice", item.q_guid), id = string.Format("{0}_q_sellprice", item.q_guid) })
</td>
<td>
€ #Html.TextBoxFor(modelItem => item.q_casecost, new { Name = string.Format("{0}_q_casecost", item.q_guid), id = string.Format("{0}_q_casecost", item.q_guid) })
</td>
</tr>
}
Note there a few key items here. First off you cant modify the Name attribute using EditorFor() so I have swapped this out to a TextBoxFor() method.
Next I am overriding the Name attribute (note it must be Name not name [lower case ignored]).
Finally the POST action runs much differently.
[HttpPost]
public ActionResult Index(FormCollection form)
{
IList<ProductViewModel> updateItems = new List<ProductViewModel>();
// form key formats
// q_casecost = {q_guid}_q_casecost
// q_sellprice = {q_guid}_q_sellprice
//load your view model from database (note mine is just static)
foreach(var item in viewModel.items)
{
var caseCostStr = form.Get(string.Format("{0}_q_casecost", item.q_guid)) ?? "";
var sellPriceStr = form.Get(string.Format("{0}_q_sellprice", item.q_guid)) ?? "";
decimal caseCost = decimal.Zero,
sellPrice = decimal.Zero;
bool hasChanges = false;
if (decimal.TryParse(caseCostStr, out caseCost) && caseCost != item.q_casecost)
{
item.q_casecost = caseCost;
hasChanges = true;
}
if(decimal.TryParse(sellPriceStr, out sellPrice) && sellPrice != item.q_sellprice)
{
item.q_sellprice = sellPrice;
hasChanges = true;
}
if (hasChanges)
updateItems.Add(item);
}
//now updateItems contains only the items that have changes.
return View();
}
So there is alot going on in here but if we break it down its quite simple. First off the Action is accepting a FormCollection object which is the raw form as a NameValuePairCollection which will contain all the keys\values of the form.
public ActionResult Index(FormCollection form)
The next step is to load your view model from your database as you have done before. The order you are loading is not important as we will interate it again. (Note i am just using the static one as before).
Then we iterate over each item in the viewmodel you loaded and now are parsing the form values out of the FormCollection.
var caseCostStr = form.Get(string.Format("{0}_q_casecost", item.q_guid)) ?? "";
var sellPriceStr = form.Get(string.Format("{0}_q_sellprice", item.q_guid)) ?? "";
This will capture the value from the form based on the q_guid again looking back at the formats we used before.
Next you parse the string values to a decimal and compare them to the original values. If either value (q_sellprice or q_casecost) are different we flag as changed and add them to the updateItems collection.
Finally our updateItems variable now contains all the elements that have a change and you can commit those back to your database.
I hope this helps.
I'm Working in ASP.NET MVC and i'm trying to combine two collections to execute in one loop i have tried ZIP method but it doesn't return anything if one collection is empty. I tried Concat Method but it is givning this error
System.Collection.Generic.ICollection<Project.Entities.TDetail> does not contains definition for 'Concat'.
My ViewModel:
public class CategoryViewModel
{
public virtual ICollection<TDetail> Details { get; set; }
public virtual ICollection<TRequest> Requests { get; set; }
}
My Loop:
#foreach (var item in Model.Details.Concat(Model.Requests))
{
}
ZIP Method Tried But Failed:
var request = Model.Requests.ToList();
var details = Model.Details.ToList();
var final = details.Zip(request, (x, y) => new { Detail = x, Request = y });
#foreach (var item in final)
{
}
I have spent my 3 days on this but couldn't find any solution, please help me with this.
i just want to list them side by side, there is no relationship between them
Then neither Concat or Zip will work for you. Concat will append items to a list ("vertically"). Zip will give you "side-by-side" collections, but will only give you as many elements as the shortest collection.
You could do a straight for loop:
var requests = Model.Requests.ToList();
var details = Model.Details.ToList();
var length = Math.Max(requests.Count, details.Count);
#for(int i=0 ; i< length ; i++)
{
if(i <= request.Count)
{
var request = requests[i];
#: html code here
}
if(i <= details.Count)
{
var detail = deatils[i]
#: html code here
}
}
Or loop separately and create two different UI elements, using styling to place them side-by-side
var requests = Model.Requests.ToList();
var details = Model.Details.ToList();
#foreach (var item in requests)
{
#: html code here
}
#foreach (var item in details)
{
#: html code here
}
I have a ListView with two columns, Boxes and Files. I'm adding items to a list of strings, and then populating the ListView with that list of strings. I want to make it so all items that are 8 characters long go into the Boxes column and all items that are 9 characters go into the Files column. So far, I've tried to iterate through using a for loop and utilize an if else statement to add the items, but I seem to be doing something wrong. Here's my current code:
public void PopulateItemsList()
{
BoxAndFileList.Items.Clear();
ScanIdBox.Text = string.Empty;
for (int i = 0; i < BoxNumberRepository._boxAndFileList.Count; i++)
{
var item = BoxNumberRepository._boxAndFileList.Item[i];
if (item.Length == 8)
{
BoxAndFileList.Items.Insert(0, item);
}
else
{
BoxAndFileList.Items.Insert(1, item);
}
}
}
I'm iterating through my list (_boxAndFileList) and trying to utilize Insert() to insert items into the specific index of the columns (Boxes is 0, Files is 1). I can clearly see that Item is a legitimate property of a string list, yet VS keeps saying that list contains no definition of it. How can I go about doing this? And also, I haven't received outside feedback on this way of doing things yet, so if there's a better way, please let me know.
Edit: BoxNumberRepository is a class that news up a list called _boxAndFileList. Code below:
public class BoxNumberRepository : Scan_Form
{
public static List<string> _boxAndFileList = new List<string>();
public void AddItem(string item)
{
_boxAndFileList.Add(item);
}
public void Delete(string item)
{
_boxAndFileList.Remove(item);
}
public IEnumerable<string> GetAllItems()
{
return _boxAndFileList;
}
}
Thanks to Alessandro D'Andria for that suggestion. That was correct. However, all the items are still just adding to the first column, even if they're 9 characters. How can I get 9 character items to add to the second column?
The problem that you are having is that you have to add both the box and file to the list item at the same time.
EDIT: Changed cartesian product to a left outer join.
EDIT: Added comments and fixed a syntax bug
private List<string> _boxAndFileList = new List<string> { "12345678", "123456789", "1234", "123456778" };
public void PopulateItemsList()
{
//clear the list
BoxAndFileList.Items.Clear();
//add the labels to the top of the listbox
BoxAndFileList.Columns.Add("Boxes");
BoxAndFileList.Columns.Add("Files");
//set the view of the list to a details view (important if you try to display images)
BoxAndFileList.View = View.Details;
//clear scan id box
ScanIdBox.Text = string.Empty;
//get all the items whos length are 8 as well as a unique id (index)
var boxes = _boxAndFileList.Where(b => b.Length == 8).Select((b, index) => new { index, b }).ToList();
//get all the items whos length are NOT 8 as well as a unique id (index)
var files = _boxAndFileList.Where(f => f.Length != 8).Select((f, index) => new { index, f }).ToList();
//join them together on their unique ids so that you get info on both sides.
var interim = (from f in files
join b in boxes on f.index equals b.index into bf
from x in bf.DefaultIfEmpty()
select new { box = (x == null ? String.Empty : x.b), file = f.f });
//the real trick here is that you have to add
//to the listviewitem of type string[] in order to populate the second, third, or more column.
//I'm just doing this in linq, but var x = new ListViewItem(new[]{"myBox", "myFile"}) would work the same
var fileboxes = interim.Select(x => new ListViewItem(new []{ x.box, x.file})).ToArray();
//add the array to the listbox
BoxAndFileList.Items.AddRange(fileboxes);
//refresh the listbox
BoxAndFileList.Refresh();
}
Your _boxAndFileList is a List<string> so you should be declare item as string type instead var type:
string item = BoxNumberRepository._boxAndFileList.Item[i];
All your code should be like this:
public void PopulateItemsList()
{
BoxAndFileList.Items.Clear();
ScanIdBox.Text = string.Empty;
for (int i = 0; i < BoxNumberRepository._boxAndFileList.Count; i++)
{
string item = BoxNumberRepository._boxAndFileList.Item[i];
if (item.Length == 8)
{
BoxAndFileList.Items.Insert(0, item);
}
else
{
BoxAndFileList.Items.Insert(1, item);
}
}
}