Why DbContext Save Only One from List of Item? - c#

I am using AspNetNet 6.
In my Page I have two [BindProperty]:
tblUserToRoute Class (Entity Class)
int[] SelectedRouteIds (Get Selected Item By User)
When client select several item in ListBox and click on save button, in my "OnPost" method I receive correct model and an array of selected value from ListBox which stored in "SelectedRouteIds" property. Everything is ok so far.
For save model for each selected item in ListBox I used "foreach" like below:
foreach (int item in SelectedRouteIds)
{
tblUserToRoute.fldRouteId = item; //set selected item
db.tblUserToRoute.Add(tblUserToRoute); //add model to repository
}
db.SaveChanges();
What I have done is: in each loop I set field value to selected item value from ListBox and then add model to context and after "foreach" loop I tried to save changes but, only one model saved to database and other model which have been passed to context not saved.
Why context cannot save multi added model? for this scenario how can I proceed?
thank you all

I changed my codes inside "foreach" like below:
db.tblUserToRoute.Add(new cesEntities.Models.cesUser.tblUserToRoute()
{
fldUserId = user.fldId,
//set item (only value which should be changed in each loop)
fldRouteId = item,
fldDateExpiry = tblUserToRoute.fldDateExpiry,
fldPermanent = tblUserToRoute.fldPermanent,
fldValid = tblUserToRoute.fldValid,
fldDefault = tblUserToRoute.fldDefault,
});
Now SaveChanges() method works correctly.
Thank you all.

Related

Add multiple items/objects to ListBox

I have 3 Dropdown Lists (could be more in future).
DropdownList1 is a parent and is populated from a database.
DropdownList2 is a child and is populated from the selected item from DropdownList1.
DropdownList3 is a child and is populated from the selected item from DropdownList2.
I would like to add the selected item to a ListBox.
The problem i have is DropdownList2 and DropdownList3 may not always have a child item, so to add the items to a ListBox, i could store their IDs but display their text.
My database table has 3 columns to save the value (ID) from the 3 dropdown lists.
My question is if i display the text of the item in the ListBox, the next step is to save the data into the table into the relevant columns (so column 1 would save data from DD1, Column 2 would save from DD2 etc) is there anyway to identify which ID the item belongs to, so i can save the correct ID to the correct column?
So a user selects item 1 from DD1 item 2 from DD2, there is no item available from DD3, so they click add which adds the item to the ListBox. When i have to save this item how could i distinguish the item added was upto DD2 therefore it needs to be added to Column2? Or is there a better approach?
Hope this makes sense
List boxes don't like to store multiple values. They can, however, store objects as their datasource.
First create a custom object, then assign the values from each of your dropdown lists to the object:
Declare a new list of your custom object first
List<myObject> list = new List<myObject>();
then assign this to your button:
private void Button1_Click(object sender, EventArgs e)
{
myObject object = new myObject(Dropdown1, Dropdown2, Dropdown3);
list.Add(object);
//assign the list to the Listbox control
ListBox.Datasource = list;
}
When you want to access the values for your query, use a foreach loop to cycle over the objects in the list, with a pointer value to access each of them.
foreach (myObject obj in list)
{
var val1 = list[obj].Dropdown1;
var val2 = list[obj].Dropdown2;
var val3 = list[obj].Dropdown3;
//enter your sql code here
}
Let me know if you want to expand further.

Adding data only to a specific Column

I'm trying to find a way to add data from one datagrid to another and for that data to be inserted to only one column at a time in my second datagrid. The specific column is created each time the Add button has been clicked.
My coding so far:
private void btnFeedbackAddSupplier_Click(object sender, RoutedEventArgs e)
{
dgFeedbackSelectSupplier.Items.Clear(); //So that my rows do not stack each other on every add
DataGridTextColumn columnSupplier = new DataGridTextColumn();
columnSupplier.Binding = new Binding("Supplier");
DataGridTextColumn columnFeedbackSupplierItem = new DataGridTextColumn();
//The 'Item' column is binded in XAML
columnSupplier.Header = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Name;
columnSupplier.IsReadOnly = true;
dgFeedbackAddCost.SelectAll(); //Selects all the rows in 1st datagrid
//Casts selected rows to my 'ViewQuoteItemList' class
IList list = dgFeedbackAddCost.SelectedItems as IList;
IEnumerable<ViewQuoteItemList> items = list.Cast<ViewQuoteItemList>();
var collection = (from i in items let a = new ViewQuoteItemList { Item = i.Item, Supplier = i.Cost }
select a).ToList();
//Adds both the column and data to the 2nd datagrid
dgFeedbackSelectSupplier.Columns.Add(columnSupplier);
foreach (var item in collection)
dgFeedbackSelectSupplier.Items.Add(item);
}
My reason for wanting to add the data to only one separate column at a time is because the data is different each time I want to add it to my 2nd datagrid and it overwrites any previous data that was entered in older add's.
EDIT: I Here are some images of what my current problem is
Here I add the first company and it's values. Everything works fine
Here I add the second company with it's new values, but it changes the values entered with the first company. This is my big problem. So you can see how my values are changed from the first to the second image
I think your problem here is that all your columns are bound to the same property: Supplier. Since you're updating that property everytime, all columns are assigned the same value. In the end, there's only one Supplier property for each row, so you can't show a different value for that single property on each column since everytime you change that property's value, the Bindings get notified and update themselves.
Maybe you could try using a OneTime Binding instead of a regular one. That way, the cells would retain the value they had when you first added them to the DataGrid. But for that to work, you should avoid clearing the DataGrid's items list, since re-adding the items would force them to rebind again.
Another option would be having a list of suppliers in your Supplier property, and have each column bind to an index of that list.
private void btnFeedbackAddSupplier_Click(object sender, RoutedEventArgs e)
{
// ...
columnSupplier.Binding = new Binding(string.Format("Supplier[{0}]", supplierColumnIndex));
// ...
var supplierCosts = new List<int>();
// ...
// Fill the list with the Costs of the Suppliers that correspond to each column and item
// ...
var collection = (from i in items let a = new ViewQuoteItemList { Item = i.Item, Supplier = supplierCosts }
select a).ToList();
//Adds both the column and data to the 2nd datagrid
dgFeedbackSelectSupplier.Columns.Add(columnSupplier);
foreach (var item in collection)
dgFeedbackSelectSupplier.Items.Add(item);
}

How to populate a dropdownlist by an action from another drop down list?

I'm working with MVC 4.0 and I'd need a page with 3 drop downlists and a table.
When an item is selected from DDL1 (e.g. Users) then DDL2 (e.g. Accounts) is populated.
When an item is selected from DDL2 (Accounts) then DDL3 (e.g. Cards) is populated.
When an item is selected from DDL3 then the table has to display a list of objects e.g. Transactions (with Amount, etc).
So I created a TransactionManagementController and created an Index Action which loads the Users and displays them initially.
public ActionResult Index()
{
var vm = new VmTransactionManagement
{
Users = db.Users.ToList()
};
return View(vm);
}
<th>User:</th>
<td>#Html.DropDownListFor(m => m.SelectedUser,
Model.UsersSelectList,
"-- Select One --")</td>
Also, I created a view model for this controller: VmTransactionManagement which contains some other objects needed.
So, now how would I code so that when DDL1 is selected (userId is passed), then DDL2 gets populated?
Should I be creating a new action/view and calling it by Ajax?
If I create a new Action, then I'll have to create a new View which changes the previously selected values.
When I need to cascade drop down lists, I will use jQuery $.load and render the PartialView. An example using technique is at https://stackoverflow.com/a/1721623/1015010

adding an additional item to a listbox

I am having a difficulty adding an item to my listbox. I want to add an item at the beginning of the list box to be my 'default' item, however I will also be adding a list of items from a List using the .DataSource ... and for some reason the app is crashing whenever I try to add the items from the List and the default item at the same time. I am trying to add the items by using:
`productList.DataSource = salesManager.Products;
productList.DisplayMember = "IdAndName";
productList.ValueMember = "Id";
productList.Items.Insert(0, "ALL");`
but for some reason VS will not let me. I have also found this method and tried to apply it as well:
public void AddListLine(string lineIn)
{
productList.Items.Insert(0, "ALL");
((CurrencyManager)productList.BindingContext[productList]).Refresh();
}
However it is not working as well. Any idea please? Thanks!
The reason it isn't working is because you are attempting to add an object of type String where the rest are (I assume) of type Product or something similar. The runtime attemps to access the property IdAndName to display and the property Id for the display and value properties of the new list item and they do not exist.
Consider adding some kind of "blank" Product object instead.
public void AddListLine(string lineIn)
{
productList.Items.Insert(0, new Product { Id = "ALL", IdAndName = "ALL" });
((CurrencyManager)productList.BindingContext[productList]).Refresh();
}

Setting default item in combo box

I have a function for setting items in a combobox and one item is to be set by default like
--SELECT LIST--
public void SetOperationDropDown()
{
int? cbSelectedValue = null;
if(cmbOperations.Items.Count == 0)
{
//This is for adding four operations with value in operation dropdown
cmbOperations.Items.Insert(0, "PrimaryKeyTables");
cmbOperations.Items.Insert(1, "NonPrimaryKeyTables");
cmbOperations.Items.Insert(2, "ForeignKeyTables");
cmbOperations.Items.Insert(3, "NonForeignKeyTables");
cmbOperations.Items.Insert(4, "UPPERCASEDTables");
cmbOperations.Items.Insert(5, "lowercasedtables");
//ByDefault the selected text in the cmbOperations will be -SELECT OPERATIONS-.
cmbOperations.Text = "-SELECT OPERATIONS-";
}
else
{
if(!string.IsNullOrEmpty("cmbOperations.SelectedValue"))
{
cbSelectedValue = Convert.ToInt32(cmbOperations.SelectedValue);
}
}
//Load the combo box cmbOperations again
if(cbSelectedValue != null)
{
cmbOperations.SelectedValue = cbSelectedValue.ToString();
}
}
Can anyone suggest a way to do this?
I've rewritten this answer to clarify some stuff.
First, the "default" text must be added as combo item as well.
Usage of combo.Text property just adds descriptive text to combobox which is "lost" first time user do something with a control.
If you like to permanently have "default" text in your combo, you must add it as an combobox item.
By the code you provided, just modify the
cmbOperations.Text = "-SELECT OPERATIONS-"; to
cmbOperations.Items.Insert(0, "-SELECT OPERATIONS-");
Note that this way you add the item "-SELECT OPERANDS-" to the 0th (read first) position in the list.
Also make sure that all your following items are increased by 1, because they are now moved by one space down in list.
Finally, put cboOperations.SelectedIndex = 0; line at the end of code. By doing so, you're telling combobox to display your "default" item initially when the form (or control) loads.
One more thing. I'm not pretty sure what do you want to achieve with the code beyond setting combo items, but if you like to check what user selected use cboOperations.SelectedIndex property which contains currently selected item in combo. You can add simple if(cboOperations.SelectedIndex == someIntValue){...}
The rest is your program logic ;)

Categories