Accessing Nested repeaters - c#

Greeting, I'll try to make this short and clear
I have a NumericTextBox and a Button, upon pressing the Button it tells repeater A how many times should it repeat based on the value introduced on the NumericTextBox:
protected void ButtonRepeaterA_Click(object sender, EventArgs e)
{
string x = RadNumericTextBoxRepeatsOnA.Text.Trim();
int y = Convert.ToInt32(x);
int[] RowCount = new int[y];
RepeaterA.DataSource = RowCount;
RepeaterA.DataBind();
int currentYear = DateTime.Now.Year;
for (int i = currentYear; i <= currentYear + 100; i++)
{
//DropDownCCYear.Items.Add(new RadComboBoxItem(i.ToString(), i.ToString()));
foreach (RepeaterItem item in RepeaterA.Items)
{
RadComboBox DropDownCCYear = (RadComboBox)item.FindControl("DropDownCCYear");
DropDownCCYear.Items.Add(new RadComboBoxItem(i.ToString(), i.ToString()));
}
}
}
The issue arises with repeater B, which is inside repeater A
It behaves similarly to repeater A, but I only want the button presses to affect the repeater in which the button is inside, so it won't clear the data introduced on the controls inside the other repetitions of repeater B, which is what happens if i use a "foreach repeater" as follows:
protected void ButtonRepeaterB(object sender, EventArgs e)
{
foreach (RepeaterItem item in RepeaterA.Items)
{
Repeater RepeaterB = (Repeater)item.FindControl("RepeaterB");
RadNumericTextBox RadNumericTextBoxRepeatsOnB = (RadNumericTextBox)item.FindControl("RadNumericTextBoxRepeatsOnB");
string x = RadNumericTextBoxRepeatsOnB.Text.Trim();
int y = Convert.ToInt32(x);
int[] RowCount = new int[y];
RepeaterB.DataSource = RowCount;
RepeaterB.DataBind();
}
}
Is there a "forthis repeater"-like function?
any ideas how i can approach this?

Repeaters have an ItemCommand event that I think would be useful for you. When the Button's Click event happens, the ItemCommand event will swallow it up if you haven't set the Button's Click event handler.
On the ItemCommand event you can use the e arguments to determine which button, and the sender to determine which Repeater it came from.
I was a little confused by your question, but I think this is the answer you're driving to. Does that help?

Related

Multiple link button on same cell of gridview - click event is not firing - c#

I have created multiple linkbutton on same cell of gridview row. But it's click event is not firing. On click event, I have to get StudentID defined in RowDataBound of Gridview.
protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//loop through the cell.
for (int j = 1; j < e.Row.Cells.Count; j++)
{
string[] arrLinks = null;
if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != " ")
{
arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
}
if (arrLinks != null)
{
for (int i = 0; i < arrLinks.Length; i++)
{
LinkButton btnLink = new LinkButton();
string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
btnLink.ID ="btn_" + StudentID;
btnLink.Text = StudentName + "<br>";
// btnLink.Click += new EventHandler(StudentButtonsclick);
btnLink.CommandName = "btnLink";
e.Row.Cells[j].Controls.Add(btnLink);
}
}
}
}
}
protected void gvStudent_RowCommand(sender s, GridViewCommandEventArgs e)
{
if (e.CommandName == "btnLink")
{ }
}
<asp:GridView ID="gvStudent" runat="server" AutoGenerateColumns="true"
CssClass="gridview_alter"
OnRowDataBound="gvStudent_RowDataBound" OnRowCommand="gvStudent_RowCommand">
</asp:GridView>
Ok, the problem is that controls that require events that are created "after" the page has been rendered cannot really be wired up. You would have to move the code to a earlier event. So you are free to add controls, but they will in "most" cases be rendered TOO LATE to have events attached. Thus when you click on the link button, nothing fires.
So there are two solutions I can think of that will work.
First, set the control to have a a post back URL, and include a parameter on that post back.
eg this:
Dim lnkBtn As New LinkButton
lnkBtn.Text = "<br/>L" & I
lnkBtn.ID = "cL" & I
lnkBtn.PostBackUrl = "~/GridTest.aspx?r=" & bv.RowIndex
If you put a PostbackUrl, then when you click on the button, the page will post back. However, the grid row events such as rowindex change, or row click event etc. will NOT fire. So, if you willing to have a parameter passed back to the same page as per above, then you can pass the 1-3 (or 1-N) values you have for each control.
Of course that means you now have a parameter on the web page URL (and users will see this). You of course simply pick up the parameter value on page load with the standard
Request.QueryString["ID"] or whatever.
However, another way - which I think is better is to simple wire up a OnClickClick() event in js, and thus do this:
I = 1 to N
Dim lnkBtn As New LinkButton
lnkBtn.Text = "<br/>L" & I
lnkBtn.ID = "cL" & I
lnkBtn.OnClientClick = "mycellclick(" & I & ");return false;"
Now in above note how I am passing "I" to the js routine. You would pass your 200, 300 or whatever value you want.
then you script will look like this:
<script>
function mycellclick(e) {
__doPostBack("MySelect", e);
}
</script>
So above simply takes the value passed from the cell click (and linkbutn), and then does the postback with a dopostback. I used "MySelect", and you can give that any name you want.
Now, in the on-load event, you can simply go like this:
If Request("__EVENTTARGET") = "MySelect" Then
Dim mypassvalue As String = Request("__EVENTARGUMENT").ToString
Debug.Print("row sel for MySelect = " & mypassvalue)
End If
So, you are 100% correct - clicking on those controls does NOT fire server side event, and they are wired up too late for this to occur. so you can and often do say add some columns or controls to a gridview, but they are created and rendered TOO LATE for the events to be wired up (and thus they don't fire when clicked on).
But, you can add a postback to the lnkbutton, and you can also add a OnClickClick() event (JavaScript function call) and they will both work. I don't like parameters in the URL appearing when you click, so I think the js script call as per above works rather nice.
So while in the comments I noted (and suggested) that you have to set the CommandName="Select". This suggesting still holds true (without CommandName = select, then the rowindex will not fire. You can't use just ANY name - it MUST be select. However this ONLY works if the control is part of the grid and not added on the fly. As noted, it might be possible to move the grid event to "earlier" event (page initialize) but it going to be a challenge and will require you to re-organize the page. The most clean, and one that does not require parameters in the URL is adding that js OnClientClick() event. You can however set the controls postbackurl and along with a parameter in the URL, and that also can work well if you open to URL with parameters (I don't like them).
I would recommend using CommandName and OnRowCommand event for GridView. Here is how you should do it:
protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//loop through the cell.
for (int j = 1; j < e.Row.Cells.Count; j++)
{
string[] arrLinks = null;
if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != " ")
{
arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
}
if (arrLinks != null)
{
for (int i = 0; i < arrLinks.Length; i++)
{
LinkButton btnLink = new LinkButton();
string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
btnLink.ID = "btn_" + StudentID; // Good to concatenate a string instead just a number in the ID.
btnLink.Text = StudentName + "<br>";
btnLink.CommandName = "btnLink"; // Add a CommandName
e.Row.Cells[j].Controls.Add(btnLink);
}
}
}
}
}
protected void GridView1_RowCommand(sender s, GridViewCommandEventArgs e)
{
if (e.CommandName == "btnLink")
{
// Link Button was clicked.
var linkButton = (LinkButton)sender;
if (linkButton != null)
{
var studentId = linkButton.ID.Replace("btn_", ""); // Remove the concatenated string from the id.
// Do stuff with the student id.
// I would highly not recommend getting the id from a button element, as it could be modified using browser inspect elements. Instead use, GridView DataKeys.
}
}
}
You should add RowCommand event in your GridView as well to get it going. e.g:
<asp:GridView runat="server" ID="GridView1" OnRowCommand="GridView1_RowCommand">
<!-- Rest of the elements -->
</asp:GridView>

Visibility of buttons in gridview when selecting a row ASP.net c#

Is it possible to make the edit button on the right side of my gridview table visible when selecting a row and when I select another row the previous row's edit button will disappear. Can you please help me coz I really need it to be done. Thanks!
protected void TraineeGrid_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
for (int i = 0; i < TraineeGrid.Rows.Count; i++)
{
if (TraineeGrid.SelectedIndex == i)
{
TraineeGrid.Rows[i].Cells[1].Visible = true;
}
}
}

Fill Textbox with Data from RadGrid

When I click on an item I would like to fill my TextBox with numbers from a column from Grid2 after Grid1 is clicked. Right now if I click on an item in Grid1 it will then run a procedure that will fill Grid2 with data. Here is an example of the current functionality with picture attached, I click an item from Grid1 and it has 3 results, my textbox will still display as an empty textbox. Then I click another item in Grid1 and now my textbox will display the 3 results from the previously clicked item. How can I display the correct numbers in my textbox after an item is selected in Grid1.
I have tried a few different methods including:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
divDetails.Visible = true;
RadTextBox1.Text = "";
for (int i = 0; i < Grid_Product_List_Details.Items.Count; i++)
{
RadTextBox1.Text += Grid_Product_List_Details.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
}
and:
protected void Grid_Product_List_Details_PreRender(object sender, EventArgs e)
{
RadGrid grid = (RadGrid)sender;
if (grid.Items.Count > 0)
{
RadTextBox1.Text = "";
}
for (int i = 0; i < grid.Items.Count; i++)
{
RadTextBox1.Text += grid.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
RadTextBox1.DataBind();
}
and this:
protected void Grid_Product_List_Header_SelectedIndexChanged(object sender, EventArgs e)
{
RadTextBox1.Text = "";
for (int i = 0; i < Grid_Product_List_Details.Items.Count; i++)
{
RadTextBox1.Text += Grid_Product_List_Details.Items[i].GetDataKeyValue("number").ToString() + "\n";
}
}
But those aren't working. Any suggestions?
Try to change your code a little bit.
RadTextBox1.Text = "";
foreach (GridDataItem dataItem in Grid_Product_List_Details.Items)
{
RadTextBox1.Text += dataItem.GetDataKeyValue("number").ToString() + "\n";
}
RadTextBox1.DataBind();
This should work though I suspect your earlier code should work too.
I ended up creating a procedure which fills the textbox after an item is clicked so the most recent data appears.
Try the ItemDataBound event of the second grid. You will have access to all of its data so you can put that in the RadTextBox. I suspect you provide a data source to the second grid in the SelectedIndexChanged of the first, so its Rebind() method should be called and then you will get the ItemDataBound fired for each of its rows.
Also, if you are using AJAX - disable it. It is possible that something does not get properly updated with the partial rendering. If things work fine with full postbacks, examine the responses and see why the textbox is not included in the first request so you can know how to tweak your AJAX setup.

How to pass a text while firing an event?

I need to pass a checkeditem of a checklistbox while firing an event from a dynamic checklistbox. The code snippet is provided below with comments...
I'm facing an issue with the same piece of code. On mouse double click event its throwing an exception saying IndexoutofRange. Its working fine with the index value 0.Please help 2 solve me both.
private void clbTables_MouseDoubleClick(object sender, MouseEventArgs e)
{
int indexofselectedtable;
indexofselectedtable = Convert.ToInt32(clbTables.SelectedIndex);
if (clbTables.CheckedItems.Count != 0)
{
Metadata metadataobj = new Metadata(dbProperties);
DBList = metadataobj.GetColumns(clbTables.CheckedItems[indexofselectedtable].ToString()); // This throws an error on checking an item of index>0.
for (int j = 0; j < DBList.Count; j++)
{
chklistcolumns.Name = "chklist" + j++;
chklistcolumns.Items.Add(DBList.ElementAt(j));
}
this.Controls.Add(chklistcolumns);
chklistcolumns.ItemCheck += new ItemCheckEventHandler(OnCheckListBoxItemCheck);
}
}
private void OnCheckListBoxItemCheck(object sender, ItemCheckEventArgs args) //need to pass the tablename which can be got from the object clbTables
{
Columns columnobj = new Columns();
columnobj.ColumnName = this.Text;
columnobj.Id = this.Name;
columnobj.TableName= // need to get the tablename from the object clbtables
}
I think I see what the issue here is, you are trying to match the selected index of your CheckedListBox with an index in the CheckedItems collection, but it doesn't work that way.
Consider this: you have 10 items in your CheckedListBox, and three of them are checked. That gives you .Items[10] and .CheckedItems[3]. If then you double click on the 7th item in the CheckedListBox, your SelectedIndex will be 6, but there will only be three items in the CheckedItems collection. So when you try to read clbTables.CheckedItems[6] you are going to be outside of the range of that collection.
clbTables.CheckedItems is another collection. You can't use clbTables.SelectedIndex in it.
Why not just to use SelectedValue property?

C# WinForm Datagrid doubleclick event

Is there a doubleclick event for a datagrid? I'm trying to use this code to open a details form when the user doubleclicks on a row.
http://www.codeproject.com/KB/grid/usingdatagrid.aspx
I tried adding it by doubleclicking on the control, but it gives dataGrid1_Navigate instead.
What you get when you double click a control in design mode is the event the designers of the control thought would be the most used, in this case it's Navigate.
But yes, this control has two double click events:
public partial class Form1 : Form
{
DataGrid grid = new DataGrid();
public Form1()
{
InitializeComponent();
grid.DoubleClick += new EventHandler(grid_DoubleClick);
grid.MouseDoubleClick += new MouseEventHandler(grid_MouseDoubleClick);
grid.Dock = DockStyle.Fill;
this.Controls.Add(grid);
}
void grid_MouseDoubleClick(object sender, MouseEventArgs e)
{
}
void grid_DoubleClick(object sender, EventArgs e)
{
}
}
However, both of these events run when you double click anywhere on the control and they don't directly give you information on what row was selected. You might be able to retrieve the row double clicked in the grid_MouseDoubleClick handler by getting it from the control based on the point being clicked (e.Location), that's how it works in the TreeView control for example. At a quick glance I didn't see if the control has such a method. You might want to consider using DataGridView instead, if you don't have a particular reason to use this control.
Sounds like you need a way to get a list of all the events for a given control, rather than finding the default event (which is what VS gives you when you double click a control in the designer)
There are a few ways of doing this:
One way Select the grid.
Then click the events icon to turn the properties window into a list of events, then doubel click the event you want to strart coding the event.
Alternatively, switch to code view, select the grid in the drop down list of objects at the top left of the code window, then select the event you want from the list of all the events for that control in the event list (top right of the code window)
I tried #steve76's code, but had to tweak it slightly to work in a Windows Embedded CE 6.0 system. Here is what worked for me.
private void dataGrid1_DoubleClick(object sender, EventArgs e)
{
Point pt = dataGrid1.PointToClient(Control.MousePosition);
DataGrid.HitTestInfo info = dataGrid1.HitTest(pt.X, pt.Y);
int row;
int col;
if (info.Column < 0)
col = 0;
else
col = info.Column;
if (info.Row < 0)
row = 0;
else
row = info.Row;
object cellData = dataGrid1[row, col];
string cellString = "(null)";
if (cellData != null)
cellString = cellData.ToString();
MessageBox.Show(cellString, "Cell Contents");
}
Perhaps you can use the DataGridView.CellContentDoubleClick event.
Example:
private void DataGridView1_CellContentDoubleClick(Object sender, DataGridViewCellEventArgs e) {
System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
messageBoxCS.AppendFormat("{0} = {1}", "ColumnIndex", e.ColumnIndex );
messageBoxCS.AppendLine();
messageBoxCS.AppendFormat("{0} = {1}", "RowIndex", e.RowIndex );
messageBoxCS.AppendLine();
MessageBox.Show(messageBoxCS.ToString(), "CellContentDoubleClick Event" );
}
If that is not what you are looking for, you can find other events in the reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview_events.aspx

Categories