Adding Rows to Temporary GridView - asp.net

I want to have an ASP.net page where the user can add rows to a grid view (think typing values into a textbox and clicking Add to add to the grid view). Clicking a submit button would then persist all rows to the database.
For a low traffic site, what reasonably easy solution would you recommend to achieve this?

I've done this a few times. The basic premise of my solution is that you load the data into a local collection, and store this in the ViewState of the page.
List<MyObject> lst = new List<MyObject>();
// Populate the list from the database here
// Store this list in the ViewState
ViewState["List"] = lst;
I then have a function which binds this list to the GridView, which I call in the first Page_Load, and any function which modifies this list:
function BindList() {
List<MyObject> lst = (List<MyObject>) ViewState["List"];
GridView1.DataSource = lst;
GridView1.DataBind();
}
To add a new item...
function cmdAdd_Click(object sender, EventArgs e) {
// Retrieve list from ViewState
List<MyObject> lst = (List<MyObject>) ViewState["List"];
// Add the new item
MyObject newObj = new MyObject(); // Populate this from your form
lst.Add(newObj);
// Update the list in the ViewState
ViewState["List"] = lst;
// Update the grid to show the new item
BindList();
}
When you want to persist all of the items to the database, simply retrieve the list from the ViewState.

Related

Find ListBoxes in ASP .NET

i have created dynamic listboxes (4 to 10) in ASP.NET.
and my question is , How do i find the dynamically created listboxes using c#?
thanks
Sure... and i appreciate your help . below code i am using for creating dynamic LB
protected void btndyfilter_Click(object sender, EventArgs e)
{
int numberOfListBox = lbFilter.GetSelectedIndices().Length;
string lbname = lbFilter.SelectedValue;
for (int i = 0; i < numberOfListBox; i++)
{
ListBox listb = new ListBox();
ListItem lItem = new ListItem();
listb.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple;
listb.Height = 150;
listb.Width = 200;
lItem.Value = i.ToString();
lItem.Text = lbname;
listb.Items.Add(lItem);
panFilter.Controls.Add(listb);
//once we created the LB dynamically i need to populate each LB with the corresponding values
connstr2 = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
conn2.ConnectionString = connstr2;
conn2.Open();
CubeCollection CubeList = conn2.Cubes;
string cb = ddlCubeList.SelectedItem.Text;
//need to remove the Hardcoded Code
foreach (Member dimem in CubeList[cb].Dimensions["Date"].Hierarchies["Calendar Date"].Levels["Date"].GetMembers())
{
ListItem Memlist = new ListItem();
Memlist.Text = dimem.UniqueName;
lbFilter.Items.Add(Memlist);
}
}
panFilter.Visible = true;
panCubeDef.Visible = true;
}
so this will create the LB i believe :)... and Inside the commented code i need to use to populate for each LB item ..perhaps it bit hardcoded which i need to remove. so i all dynamic LBs are populated then the selected items from all LBs will come into the where clause in my MDX query..hope i did not confuse you
There is 2 way either you can store dynamic control detail with dictionary or just find when you want to use it using some code like this
Control GetControlByName(string Name)
{
foreach(Control c in this.Controls)
if(c.Name == Name)
return c;
return null;
}
while generating ListBox dynamically, give ListBox ID as:
lstBoxNo1, lstBoxNo2. lstBoxNo3 etc. where 1,2,3(no) will be from count.
like
int count=1;
generate listbox control
listboxid=lastBoxNo+count;
count++
`by doing this, u have control over id's.
else use
http://stackoverflow.com/questions/3731007/using-findcontrol-to-find-control
using this link to understand findcontrol.
The points that you wont to find that dynamic controls are.
The moment you first render the page.
On every other post back.
In the case of 1, then you better keep a variable on your page that keep that creations.
In the case of 2, when you have post back, you need to store somehow the creations of your control in the page when you render it. One good place is to keep that information on the viewstate.
You can also on the post back, just to check if you have any post back valued from controls that you have named with a serial numbering starting from 1, eg You start looking if you have post back from ControlName_1, then ControlName_2, and when you not found any other value you end.

How can I retrieve a subset of data from entity object data source and pass to another page

I am playing about just now trying to teach myself a little bit about the entity framework.
I have a Gridview data bound to a Entity Date Source using the Entity Framework. If I select certain items in that list I then wish to redirect another page and populate another gridview with just the items selected (but with more detail, different includes/navigation properties)
This is probably the most simple thing but I have spent 2 hours banging my head on the wall trying to get this to work.
Essentially I have a continue button which when clicked should identify all the UIDs (a column in the gridview) of the rows and allow me to subset to just these rows and pass them to another page to be rebound to another datagrid
Any ideas???
Well, the big picture is that you should get those IDs, pass them to the other page, and then use a query with Contains; see this question for an idea of how to use it:
How search LINQ with many parametrs in one column?
Assuming you haven't used DataKeys in your GridView, this would be my approach.
Page 1
protected void Button1_Click(object sender, EventArgs e)
{
var checkedItems = new List<int>();
foreach (GridViewRow row in GridView1.Rows)
{
var checkbox = (CheckBox)row.FindControl("CheckBox1");
if (checkbox.Checked)
{
checkedItems.Add(int.Parse(row.Cells[1].Text));
}
}
Session["checkedItems"] = checkedItems;
Response.Redirect("Page2.aspx");
}
Page 2
protected void Page_Load(object sender, EventArgs e)
{
var checkedItems = (List<int>)Session["checkedItems"];
Session["checkedItems"] = null;
foreach (var checkedItem in checkedItems)
{
Response.Write(checkedItem);
}
}
Using the IDs in the checkedItems List you can now query those from you DB and finally assign the Result to your GridView on the second page.
Instead of using Session you could pass the IDs via QueryString.

ListBox switch items asp.net jquery

I've two ListBox (second one is empty on page load) and two buttons which switch items between those ListBox.However,im using Jquery two switch items,which means there are no Postbacks.Once,ive finished,i click another button to save the items from the second List,this time using PostBack.
When it runs on server,ASP.NET does not recognize any item on the list,showing listbox2.items.count = 0(zero),but im sure that list does have items.
I wonder if add items to the list without postbacks is the problem;
Any suggestions?
code trying to get list:
try
{
estabelecimentos = new List<int>();
int x = lstSelect.Items.Count;//always 0,but list isnt empty
estabelecimentos = lstSelect.Items.Cast<ListItem>().Select(v => int.Parse(v.Value)).ToList();
}
catch(Exception ex)
{
divErro.Visible = true;
lblErro.Text = ex.Message;
return;
}
You are correct, when you postback to the server the datasource of the second list is read out of the ViewState (which had no items in it). You could store the second list's data in a hidden input (client side) or you could do postbacks to update the second list.

Programmatically add UserControl with events

I need to add multiple user controls to a panel for further editing of the contained data. My user control contains some panels, dropdown lists and input elements, which are populated in the user control's Page_Load event.
protected void Page_Load(object sender, EventArgs e)
{
// populate comparer ddl from enum
string[] enumNames = Enum.GetNames(typeof (SearchComparision));
var al = new ArrayList();
for (int i = 0; i < enumNames.Length; i++)
al.Add(new {Value = i, Name = enumNames[i]});
scOperatorSelection.DataValueField = "Value";
scOperatorSelection.DataTextField = "Name";
...
The data to be displayed is added to the user control as a Field, defined above Page_Load. The signature of the events is the following:
public delegate void ControlStateChanged(object sender, SearchCriteriaEventArgs eventArgs);
public event ControlStateChanged ItemUpdated;
public event ControlStateChanged ItemRemoved;
public event ControlStateChanged ItemAdded;
The update button on the user control triggers the following method:
protected void UpdateCriteria(object sender, EventArgs e)
{
var searchCritCtl = (SearchCriteria) sender;
var scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = searchCritCtl.CurrentCriteria.CriteriaId,
SearchComparision = ParseCurrentComparer(searchCritCtl.scOperatorSelection.SelectedValue),
SearchField = searchCritCtl.scFieldSelection.SelectedValue,
SearchValue = searchCritCtl.scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
}
The rendering page fetches the data objects from a storage backend and displays it in it's Page_Load event. This is the point where it starts getting tricky: i connect to the custom events!
int idIt = 0;
foreach (var item in _currentSearch.Items)
{
SearchCriteria sc = (SearchCriteria)LoadControl("~/content/controls/SearchCriteria.ascx");
sc.ID = "scDispCtl_" + idIt;
sc.ControlMode = SearchCriteriaMode.Display;
sc.CurrentCriteria = item;
sc.ItemUpdated += CriteriaUpdated;
sc.ItemRemoved += CriteriaRemoved;
pnlDisplayCrit.Controls.Add(sc);
idIt++;
}
When first rendering the page, everything is displayed fine, i get all my data. When i trigger an update event, the user control event is fired correctly, but all fields and controls of the user control are NULL. After a bit of research, i had to come to the conclusion that the event is fired before the controls are initialized...
Is there any way to prevent such behavior / to override the page lifecycle somehow? I cannot initialize the user controls in the page's Init-event, because i have to access the Session-Store (not initialized in Page_Init).
Any advice is welcome...
EDIT:
Since we hold all criteria informations in the storage backend (including the count of criteria) and that store uses the userid from the session, we cannot use Page_Init... just for clarification
EDIT #2:
I managed to get past some of the problems. Since i'm now using simple types, im able to bind all the data declaratively (using a repeater with a simple ItemTemplate). It is bound to the control, they are rendered in correct fashion. On Postback, all the data is rebound to the user control, data is available in the OnDataBinding and OnLoad events, everything looks fine.
But as soon it enters the real event (bound to the button control of the user control), all field values are lost somehow...
Does anybody know, how the page lifecycle continues to process the request after Databinding/Loading ? I'm going crazy about this issue...
Dynamic controls are can be a nightmare. The trick is to make sure you rebind everything on the postback.
I figured out a solution ;)
If i work with the OnCommand event on the buttons inside the usercontrol, i can pass a CommandArgument. Now im binding the collection identifier to the CommandArgument parameter of the button which enables me to handle all postbacks inside the usercontrol.
<asp:Button ID="scUpdate"
runat="server"
Text="Update"
OnCommand="HandleCommand"
CommandName="update"
CommandArgument='<%# CriteriaId %>' />
This declaration preserves the CriteriaId (a Guid) throughout postbacks and enables me to identify the modified entry on the underlying collection (managed on the page). The following code snippet shows how the event to the subscribing page is triggered.
scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = new Guid(e.CommandArgument.ToString()),
SearchComparision = ParseCurrentComparer(),
SearchField = scFieldSelection.SelectedValue,
SearchValue = scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
Maybe this answer helps somebody so i'll just post it ;)

TreeView manipulation, saving adding etc

Here is what I am trying to do. I have a TreeView server side control (asp.net 2.0) and I need the user to be able to add nodes to it, then after all the nodes desired are added, the data should be saved to the database.
Here are some things I would like to pay attention to:
1) I don't want to save the tree data each time the new node is added, but rather keep the data in session until the user decides to save the entire tree. The question here is: can I bind the tree to ArrayList object and keep that object in session (rather than keeping the whole tree in session)? Then each time the node is added I will have to rebind the tree to the ArrayList rather than database.
2) I wish to minimize ViewState, any tips? What works best: compressing viewstate or keeping it all on the server at all times?
Thanks!
Use TreeNodeCollection as your internal array to hold in either ViewState or Session. Here's a rough mock-up of an approach you can use; far from perfect, but should set you on the right track.
TreeView tv = new TreeView();
// Button click event for 'Add Node' button
protected void AddNode(object sender, EventArgs e)
{
if (SaveNodeToDb(txtNewNode.Text, txtNavUrl.Text))
{
// Store user input details for new node in Session
Nodes.Add(new TreeNode() { Text = txtNewNode.Text, NavigateUrl = txtNavUrl.Text });
// Clear and re-add
tv.Nodes.Clear();
foreach (TreeNode n in Nodes)
tv.Nodes.Add(n);
}
}
public bool SaveNodeToDb(string name, string url)
{
// DB save action here.
}
public TreeNodeCollection Nodes
{
get
{
if (Session["UserNodes"] ! = null)
return (TreeNodeCollection) Session["UserNodes"];
else
return new TreeNodeCollection();
}
set
{
Session["UserNodes"] = value;
}
}

Resources