I have a listbox with a list of items that get loaded when you navigate to a certain page. Then I have an on click that passes parameters to an AddProducts method. That method is what loops through all selected items and inserts values from the fields filled in as well as takes the values from the listItems and adds them as parameters to a stored procedure.
The problem I'm running into is that when looping through the listItems
if(selectedItem.Selected) is returning false, but in my method where I load the listbox I initialize a SelectedValue so I'm not sure why it's giving me the error message I have for no selected items. I was able to get it to work yesterday before I moved LoadListBoxCategories outside of LoadAddData but unsure as to why that would have any effect to if(listItem.Selected).
I'm relatively new to asp.net so any help/ explanation as to why my code isn't working is extremely appreciated. I've spent the last three days trying to figure this out and haven't found a solution that works.
Code:
Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
if (Session[IS_LOGGED_IN] == null)
{
Response.Redirect("/utilities/companydata/login.aspx", true);
return;
}
gvTextInputs.RowEditing += new GridViewEditEventHandler(gvTextInputs_RowEditing);
if (!IsPostBack)
{
string pageId = Request.QueryString["pageid"];
string productId = Request.QueryString["productid"];
/* Add Mode */
if (!string.IsNullOrEmpty(pageId))
{
SetMode(MODE_ADD, "");
LoadAddData(pageId);
LoadListBoxCategories(pageId);
}
else if (!string.IsNullOrEmpty(productId))
{
string imageServer;
if (LoadProductData(productId, out imageServer))
{
InitImageGridview();
InitTextGridview();
InitStaticGridview();
SetMode(MODE_EDIT, imageServer);
SetImageServer(imageServer);
}
else
{
//TO DO - Return Error
}
}
}
else
{
InitImageGridview();
InitTextGridview();
InitStaticGridview();
}
}
Load ListBox:
private void LoadListBoxCategories(string pageId)
{
listBoxCategories.Visible = true;
//This gets query is so I can store the CompanyId and the CombinedValue data from pageId
string select = "SELECT companyName, cl.GbsCompanyId, cl.companyId, wpt.productTypeId, productName, (CAST(wp.pageId as varchar(200)) +'|'+ CAST(wp.productTypeId as varchar(200)) + '|' ) AS CombinedValue FROM CompanyList cl, WtpPages wp, WtpProductTypes wpt WHERE cl.companyId=wp.companyId AND wpt.productTypeId=wp.productTypeId AND wp.pageId=#pageId";
SqlDataSource connectionId = new SqlDataSource(DB_CONNECT, select);
connectionId.SelectParameters.Add("pageId", pageId);
DataView dView = (DataView)connectionId.Select(DataSourceSelectArguments.Empty);
if (dView.Table.Rows.Count == 1)
{
string companyId = dView.Table.Rows[0]["companyId"].ToString();
string curCategoryProductTypeId = dView.Table.Rows[0]["CombinedValue"].ToString();
// EXEC MCAdmin_GetAllCategoriesByCompanyId #companyId
// Lists All Categories #companyId has Active
string selectLoadData = "EXEC MCAdmin_GetAllCategoriesByCompanyId #companyId";
SqlDataSource conn = new SqlDataSource(DB_CONNECT, selectLoadData);
conn.SelectParameters.Add("companyId", companyId);
lstCategoriesBox.Items.Clear();
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
// Pre-selects the value of the productTypeId you are trying to add a product for
// to send later run against a foreach insert in AddProduct()
lstCategoriesBox.SelectedValue = curCategoryProductTypeId;
testOutcomeCategory.InnerText = curCategoryProductTypeId;
lstCategoriesBox.DataSource = conn;
lstCategoriesBox.DataBind();
}
}
AddProduct:
private string AddProduct(string companyId, out string errMsg)
{
foreach (ListItem selectedItem in lstCategoriesBox.Items)
{
if (selectedItem.Selected)
{
// assign current productTypeId & pageId from selected Categories new CombinedValue column
string[] splitColumnValue = selectedItem.Value.Split('|');
string selectedPageId = splitColumnValue[0].ToString();
string selectedProductTypeId = splitColumnValue[1].ToString();
SqlDataSource connnection = new SqlDataSource(DB_CONNECT, "");
connnection.InsertCommand = "EXEC MCAdmin_AddProductFromClassic #pageId, #productTypeId, #productCode, #imgDirectory, #numSides, #sortOrder, #isActive, #template, #template2, #template3, #EditorJson, #MockupTemplateBase, #MockupTemplateTreatment, #BorderDefault ";
connnection.InsertParameters.Add("pageId", selectedPageId);
connnection.InsertParameters.Add("productTypeId", selectedProductTypeId);
connnection.InsertParameters.Add("productCode", txtProductCode.Text);
connnection.InsertParameters.Add("numSides", ddlNumSides.SelectedValue);
connnection.InsertParameters.Add("sortOrder", txtSortOrder.Text);
connnection.InsertParameters.Add("isActive", ddlActive.SelectedValue);
connnection.InsertParameters.Add("template", txtTemplate1.Text);
connnection.InsertParameters.Add("template2", txtTemplate2.Text);
connnection.InsertParameters.Add("template3", txtTemplate3.Text);
connnection.InsertParameters.Add("EditorJson", txtJson.Text);
connnection.InsertParameters.Add("MockupTemplateBase", txtMockupTemplateBase.Text);
connnection.InsertParameters.Add("MockupTemplateTreatment", txtMockupTemplateTreatment.Text);
connnection.InsertParameters.Add("BorderDefault", txtBorderDefault.Text);
/* Special Product Code for Upload Artwork Business Card */
if (txtProductCode.Text.ToUpper() == "BPFAH1-001-100")
{
connnection.InsertParameters.Add("imgDirectory", "/images/business-cards/general/");
}
else
{
connnection.InsertParameters.Add("imgDirectory", ddlImgDir.SelectedValue);
}
int result = connnection.Insert();
if (result > 0)
{
SqlDataSource connect = new SqlDataSource(DB_CONNECT, "");
connect.SelectCommand = "SELECT TOP 1 wtpProductId FROM WtpProducts ";
connect.SelectCommand = "WHERE productTypeId=#productTypeId AND pageId=#pageId DESC ";
connect.SelectParameters.Add("pageId", selectedPageId); //
connect.SelectParameters.Add("productTypeId", selectedProductTypeId); //
DataView dView = (DataView)connect.Select(DataSourceSelectArguments.Empty);
if (dView.Table.Rows.Count == 1)
{
string wtpProductId = dView.Table.Rows[0]["wtpProductId"].ToString();
errMsg = "";
return wtpProductId;
}
else
{
errMsg = "ERROR: Could not get productId of newly created Product.";
return "0";
}
}
else
{
errMsg = "ERROR: Could not add WtpProduct record to DB";
return "0";
}
}
else
{
errMsg = "ERROR: You must select a Category";
return "0";
}
}
errMsg = "ERROR: Did not make it into the foreach loop";
return "0";
}
OnClick method:
protected void OnClick_btnAddProduct(object sender, EventArgs e)
{
string pageId = Request.QueryString["pageid"];
testOutcomeCategory.InnerText = lstCategoriesBox.SelectedValue; // This proves that I have something selected!!!
string select = "SELECT companyName, cl.GbsCompanyId, cl.companyId, wpt.productTypeId, productName, baseImgDirectory, templateDirectory, wp.imageServer FROM CompanyList cl, WtpPages wp, WtpProductTypes wpt WHERE cl.companyId=wp.companyId AND wpt.productTypeId=wp.productTypeId AND wp.pageId=#pageId";
SqlDataSource conn = new SqlDataSource(DB_CONNECT, select);
conn.SelectParameters.Add("pageId", pageId);
DataView dView = (DataView)conn.Select(DataSourceSelectArguments.Empty);
if(dView.Table.Rows.Count == 1)
{
string companyId = dView.Table.Rows[0]["companyId"].ToString();
if (!string.IsNullOrEmpty(pageId))
{
string errMsg;
string productId = AddProduct(companyId, out errMsg);
if(productId != "0")
{
Response.Redirect("/utilities/companydata/add-edit-wtp-product.aspx?productid=" + productId, true);
SetStatusMsg("Success", false);
}
else
{
SetStatusMsg(errMsg, true);
}
}
}
}
The list box instance is recreated on the server-side during the postback (as well as entire page). You do not set the selected items in the Page_Load event handler - if (!IsPostBack) goes to else branch. This is why you don't see them.
Ok,
lstCategoriesBox.Items.Clear();
Ok, above goes nuclear - blows out the list, blows out the selection.
Ok, that's fine
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
Ok, above adds a new item. Should be ok, but one should setup the lb BEFORE adding any data - including that "--select--" row.
It just makes sense to "setup" the lb and THEN start adding data, right?
However, But, if above works - ok, then lets keep going, but I would setup the lb before adding any rows of data. Say like this:
lstCategoriesBox.DataTextField = "productName";
lstCategoriesBox.DataValueField = "CombinedValue";
lstCategoriesBox.Items.Add(new ListItem("--Select--", null));
Now, the next line:
lstCategoriesBox.SelectedValue = curCategoryProductTypeId;
Ouch! - we just cleared the lb, and now we trying to set it to a value? You can't do that - the lb just been cleared, right? You would need to load up the lb first, and THEN you can set it to the selected value, right?
I might be missing something here, but that lb needs to be loaded up with valid data BEFORE you attempt to set the selected value?
To test first, change following
Outcome Category.InnerText = list CategoriesBox.SelectedValue;
to
Category.InnerText = Request.Form["CategoriesBox-ClientID"]
If the data is coming in correctly, the list view cleared or reloaded when between reload and click events the page.
UPDATE: I just figured it out! So stupid but when I check if(selectedItem.Selected) since I'm looping through the ListBox items it starts at the first index of the ListBox and since the first isn't selected then that if goes to the else block. Remove the else and it works fine
I am currently working on a system. I have a datagridview with a contextmenu and an edit and delete button on it. I want to pass the value of the selected rows to a textbox when I click the edit on contextmenu.
I have successfully passed the value to the textbox but the only values that show are from the last inputted data to whatever row I click. I don't know how to get the id, can someone please help me fix my problem? :(
Here is my code:
private void BtnEdit_Click(object sender, EventArgs e)
{
frmAddEditStudent frm = new frmAddEditStudent(this);
cn.Open();
cm = new SqlCommand("SELECT s.studentID, s.studentNo, s.Lname, s.Fname, s.MI, s.gender, s.yearLevel, s.section, s.studImage, g.name, g.contactNo, g.address FROM Student s INNER JOIN Guardian g ON g.studentNo = s.studentNo WHERE g.studentNo = s.studentNo AND s.isActive = 'true' AND s.studentID = studentID", cn);
cm.Parameters.AddWithValue("studentID", lblID.Text);
for (int i = 0; i < guna2DataGridView1.Rows.Count; i += 1)
{
frm.btnSave.Enabled = false;
frm.lblTitle.Text = "Edit Student Details";
frm.lblID.Text = guna2DataGridView1.Rows[i].Cells[1].Value.ToString();
frm.txtStudentNo.Text = guna2DataGridView1.Rows[i].Cells[2].Value.ToString();
frm.txtLname.Text = guna2DataGridView1.Rows[i].Cells[3].Value.ToString();
frm.txtFname.Text = guna2DataGridView1.Rows[i].Cells[4].Value.ToString();
frm.txtMI.Text = guna2DataGridView1.Rows[i].Cells[5].Value.ToString();
frm.cboGradeLevel.Text = guna2DataGridView1.Rows[i].Cells[7].Value.ToString();
frm.cboSection.Text = guna2DataGridView1.Rows[i].Cells[8].Value.ToString();
frm.txtGuardianName.Text = guna2DataGridView1.Rows[i].Cells[9].Value.ToString();
frm.txtContactNo.Text = guna2DataGridView1.Rows[i].Cells[10].Value.ToString();
frm.txtAddress.Text = guna2DataGridView1.Rows[i].Cells[11].Value.ToString();
//Load Image
byte[] bytes = (byte[])guna2DataGridView1.Rows[i].Cells[12].Value;
MemoryStream ms = new MemoryStream(bytes);
frm.studImage.Image = Image.FromStream(ms);
//Retrieve gender value to radio button
if (guna2DataGridView1.Rows[i].Cells[6].Value.ToString() == "Male")
{
frm.rbMale.Checked = true;
}
else
{
frm.rbFemale.Checked = true;
}
}
cn.Close();
frm.ShowDialog();
It does not show up the data in the row that I selected, instead it only shows the last row in my database table.
You can get the current row or the selected rows from a datagridview in the following way (I think ID is cell with Index 1):
Console.WriteLine(guna2DataGridView1.CurrentRow.Cells[1].Value.ToString());
foreach (DataGridViewRow loRow in guna2DataGridView1.CurrentRow.SelectedRows)
{
Console.WriteLine(loRow.Cells[1].Value.ToString());
}
But you overwrite the form values in your loop every time.
It seems that your form can only display one row and not a collection.
And what about the command cm??
I have a asp combo box inside update panel with autopost back set to true.
On page Load I fill combo box as
public DataTable getProductDetails()
{
MasterAllocationDB dataHandler = new MasterAllocationDB();
DataTable dataBoxType = null;
DataRow row = null;
try
{
dataBoxType = dataHandler.GetBoxType();
if (dataBoxType != null && dataBoxType.Rows.Count > 0)
{
row = dataBoxType.NewRow();
row["Product"] = "--Select--";
dataBoxType.Rows.InsertAt(row,0);
row = dataBoxType.NewRow();
row["Product"] = "Other";
dataBoxType.Rows.InsertAt(row, dataBoxType.Rows.Count);
}
}
catch (Exception ex)
{
LogHandler.LogMessageToFile(ex, LogMode.Fatal);
}
return dataBoxType;
}
Also I have a onselectedindexchanged event binded
protected void productComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
string json = null;
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row = null;
var s = this.productComboBox.SelectedValue;
try
{
int totalNoOfItems = this.productComboBox.Items.Count;
// Make sure that Index are between "select a value" and "Other"
if (this.productComboBox.SelectedIndex > 0 && this.productComboBox.SelectedIndex < totalNoOfItems - 1)
{
//code here
}
json = new JavaScriptSerializer().Serialize(rows);
}
catch (Exception ex)
{
LogHandler.LogMessageToFile(ex, LogMode.Fatal);
}
}
As you can see I have added 2 extra rows besides the rows fetched from DB.The data rows are binding properly as I can see the same in outputed combo box values
After running I noticed that whenever I select "other" the text inside combo box gets changed
to "--select--" and control never reaches onselectedindexchanged
It works finely for all the other cases. What could be the reason?
Ok I sorted it out.
The problem is that I have only set text for the combo box not value for options.
Changed the code as
row["Product"] = "--Select--";
row["ProductID"] = "0";
row["Product"] = "Other";
row["ProductID"] = "10";
ProductId gives the value for combobox.
Happy coding
I have a website using dynamic data and linq to sql. This website runs 3 'subsites' and has a list of categories with a many to many relationship.
I have 3 tables and hence 3 objects in my dbml; Website, Categories, and CategoriesToWebsites
What I am trying to do is create a field template such that on my Categories/Edit.aspx page I can edit a category and specify which website the category belongs in.
The field template is CategoriesToWebsites_Edit.ascx, which is basically a checkbox list bound to the list of websites.
Code below:
public partial class CategoriesToWebsitesEdit : FieldTemplateUserControl
{
protected override void OnLoad(EventArgs e)
{
var dataSource = (LinqDataSource)this.FindDataSourceControl();
dataSource.Inserting += OnInserting;
dataSource.Updating += OnUpdating;
}
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
//check if website category already exists
var categoryToWebsite = oldCategory.CategoriesToWebsites.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//website category exists
if (categoryToWebsite != null)
{
// check if selected for removal, remove
if (!listItem.Selected)
{
newCategory.CategoriesToWebsites.Remove(categoryToWebsite);
}
}
//we want to insert
if (listItem.Selected)
{
//website category does not exist, add
if (categoryToWebsite == null)
{
//add selected website if not already exists
newCategory.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
}
}
private void OnInserting(object sender, LinqDataSourceInsertEventArgs e)
{
var category = (Category)e.NewObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
if(!listItem.Selected)
continue;
category.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
protected override void OnDataBinding(EventArgs e)
{
var websiteRepository = new WebsiteRepository();
var websites = websiteRepository.GetAll();
var websiteCategories = (IEnumerable<CategoriesToWebsite>)FieldValue;
foreach(var website in websites)
{
var currentWebsite = website;
var listItem = new ListItem(website.Name, website.Id.ToString())
{
Selected = websiteCategories == null ? false : websiteCategories.Any(w => w.WebsiteId == currentWebsite.Id)
};
WebsiteList.Items.Add(listItem);
}
}
}
When I go to Categories/Insert.aspx to create a new category, it runs through the OnInserting code fine and saves it to db just fine, everything seems to be working here.
On Categories/Edit.aspx it goes through the code just as I expect, but does not seem to save anything.
What am I missing? - I'm not too familiar with Dynamic Data Field Templates so any guidance will be much appreciated
Apparently I was going about this slightly wrong. I was simply updating the object in the linq data source, which wasn't being saved. So instead I go straight to the repository:
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
var repository = new Repository<CategoriesToWebsite>();
var ctw = repository.GetAll().Where(x => x.CategoryId == newCategory.Id);
foreach (var listItem in WebsiteList.Items.Cast<ListItem>())
{
var current = ctw.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//current categoriesToWebsite exists
if (current != null)
{
//if not selected, remove
if (!listItem.Selected)
repository.Delete(current);
}
//does not exist
else
{
//if selected, add
if (listItem.Selected)
repository.Save(new CategoriesToWebsite()
{
CategoryId = newCategory.Id,
WebsiteId = Convert.ToInt32(listItem.Value)
}
);
}
}
UnitOfWork.Current.SubmitChanges();
}
I'm not sure if this is the proper way to do this since the field template here is doing some updating directly to the db. But it works.
I am having problems with postbacks.
I have a dropdownlist that i add items to at runtime.
When i select a item in the dropbox a treeview is filled with items that have the same pID value as the object selected in the dropdownlist.
But when i select a node in the treeview everything goes back to "normal" state. The dropbox will go to selectindex -1 and the treeview disappear.
I have theese controllers in a master page if that matters.
This is my code.
public partial class Nemanet : System.Web.UI.MasterPage
{
nemanetDataContext dc = new nemanetDataContext();
Guid userGuid = (Guid)Membership.GetUser().ProviderUserKey;
bool reloadPeriod = true;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (reloadPeriod == true)
{
reloadPeriod = false;
var query = from n in dc.Nemanet_Navigations
where n.UserId == userGuid && n.Nav_pID == null
orderby n.Nav_Name ascending
select n;
foreach (var period in query)
{
ListItem period_listitem = new ListItem(period.Nav_Name, period.Nav_ID.ToString());
dropdown_navigation.Items.Add(period_listitem);
}
}
}
}
protected void dropdown_navigation_SelectedIndexChanged(object sender, EventArgs e)
{
treeview_Navigation.Nodes.Clear();
var query = from n in dc.Nemanet_Navigations
where n.UserId == userGuid
orderby n.Nav_Name ascending
select n;
foreach (var course in query)
{
if (course.Nav_pID.ToString() == dropdown_navigation.SelectedValue)
{
TreeNode course_node = new TreeNode(course.Nav_Name, course.Nav_ID.ToString());
course_node.NavigateUrl = "Default.aspx?navigateID=" + course.Nav_ID;
treeview_Navigation.Nodes.Add(course_node);
foreach (var chapter in query)
{
if (chapter.Nav_pID.ToString() == course_node.Value)
{
TreeNode chapter_node = new TreeNode(chapter.Nav_Name, chapter.Nav_ID.ToString());
chapter_node.NavigateUrl = "Default.aspx?navigateID=" + chapter.Nav_ID;
course_node.ChildNodes.Add(chapter_node);
foreach (var subject in query)
{
if (subject.Nav_pID.ToString() == chapter_node.Value)
{
TreeNode subject_node = new TreeNode(subject.Nav_Name, subject.Nav_ID.ToString());
subject_node.NavigateUrl = "editor.aspx?navigateID=" + subject.Nav_ID;
chapter_node.ChildNodes.Add(subject_node);
}
}
}
}
}
}
}
}
Any dynamically added elements will be gone after any postback, so you have add all of them again after every postback (your page is rebuild from the ground using the frontpage and page load).
To avoid reloading all the data from the database, store it in the Session.
Session["items"] = query;
if(IsPostBack) foreach(var period in (Collection)Session["items"]) dropdown_navigation.Items.Add(new ListItem(period.Nav_Name, period.Nav_ID.ToString()));