Reproduce a content of panel dynamically - c#

Is there any way where we can reproduce the content of a panel.For example i have a panel which has two text box .On clicking more button i would like to have another panel below which again has two text box like the first one or add two text box into the existing panel.My end goal is to add controls as the user clicks on more button and get data from those controls .This is the controls inside the panel that i would like to reproduce
any possible way where i can add the controls as shown in the layout through server side ?Please help!

There are plenty ways to solve this. You could add proper DOM elements by yourself using plain JavaScript or jQuery, or use some JS MV* frameworks, like KnockoutJS (example: http://knockoutjs.com/examples/contactsEditor.html) or AngularJS.

you can obviously add dynamic controls from code behind on button click event of 'more button'.
Click Here for more references:

If you want to achieve this on client side using jQuery, then 'closest()' (to find the source element/row to be repeated nearby to the add/remove button etc., especially if it is in a tabular/grid format) in conjunction with 'clone()' function, (to make a copy of the source element/row) and then you can paste the clone inside the target container.
The following link might help you achieve what you want:
jQuery Clone table row
But doing this in Asp.Net WebForms should be much straight forward.
Also, please be noted that, it would always be much helpful to get a quicker answer by specifying more details(eg., MVC, WebForms etc. in the description, what trials you did to find/fix the problem) and that help save other's time as well. For more info: https://stackoverflow.com/questions/how-to-ask

try this
your aspx page add
<asp:TextBox runat="server" ID="TextBox1" />
<asp:TextBox runat="server" ID="TextBox2" />
<asp:Button Text="Add" ID="btnAdd" OnClick="btnAdd_Click" runat="server" />
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("str1") %>' />
<asp:TextBox runat="server" ID="txt2" Text='<%# Eval("str2") %>' /><br />
</ItemTemplate>
</asp:Repeater>
and in code behind
protected void btnAdd_Click(object sender, EventArgs e)
{
List<temp> lst = GetItemFromRpt();
lst.Add(new temp
{
str1=TextBox1.Text,
str2 = TextBox2.Text
});
rpt.DataSource = lst;
rpt.DataBind();
}
private List<temp> GetItemFromRpt()
{
List<temp> lst = new List<temp>();
for (int i = 0; i < rpt.Items.Count; i++)
{
temp obj = new temp();
obj.str1 = ((TextBox)rpt.Items[i].FindControl("txt1")).Text;
obj.str2 = ((TextBox)rpt.Items[i].FindControl("txt2")).Text;
lst.Add(obj);
}
return lst;
}
public class temp // instead of temp you can use whatever your entity class you need
{
public string str1 { get; set; }
public string str2 { get; set; }
}

Related

C# Custom GridView

I'm not really proficient in asp.net. I Have a asp based web application and I want to create a custom GridView in order to use it whenever I have a search box and reduce redundancy in my code.
I want to have this GridView below my textbox and on text changing the GridView shows mostly searched results and a "More" button for advance search which will open a new page. Can anybody help me how can I start?
Thanks.
Here a small example of how you could achieve this. First add the necessary items needed to do a search to the aspx page. Note that the buttons have an OnCommand so that you can send a CommandName along with them.
<asp:TextBox ID="SearchField" runat="server" MaxLength="50"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="A search term is required" ValidationGroup="Search"
ControlToValidate="SearchField">
</asp:RequiredFieldValidator>
<asp:Button ID="SearchButton" runat="server" Text="Search"
OnCommand="DoSearch_Command" CommandName="Search" ValidationGroup="Search" />
<asp:GridView ID="SearchResultsGridView" runat="server" AutoGenerateColumns="true"></asp:GridView>
<asp:Button ID="MoreButton" runat="server" Text="More"
OnCommand="DoSearch_Command" CommandName="More"/>
Now in the code behind you process the button clicks of Search and More. I created some dummy data with a List, but you need to replace that with the correct data source that holds your search results (List, DataTable etc).
protected void DoSearch_Command(object sender, CommandEventArgs e)
{
//create a new item to hold search results, in this case a list
List<string> searchResults = new List<string>();
//the text from the textbox that contains the search word
string searchTerm = SearchField.Text.Trim();
//hide the 'more' button
MoreButton.Visible = false;
//add some dummy data for testing
for (int i = 1; i <= 50; i++)
{
searchResults.Add("Search result " + i);
}
//if the results are more than 10 and the click is not from the 'more' button take 10 items
if (searchResults.Count > 10 && e.CommandName == "Search")
{
searchResults = searchResults.Take(10).ToList();
//show the more button
MoreButton.Visible = true;
}
//show results in gridview
SearchResultsGridView.DataSource = searchResults;
SearchResultsGridView.DataBind();
}

not able to redirect users to another page with hyper link

I have requirement where users are redirected youtube.com by using hyperlink control using below
I want to change the URL dynamically based on drop down list selected item by using below code.
protected void ddlPType_SelectedIndexChanged(object sender, EventArgs e)
{
int x = ddlPType.SelectedIndex;
if (x == 0)
{
activateCerts.NavigateUrl = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
activateCerts.Text = "activateCerts";
activateCerts.Target = "_blank";
//activateCerts.HRef = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
}
else if (x == 1)
{
//activateCerts.Target = "_blank";
//activateCerts.HRef = "http://www.youtube.com/watch?v=hk3hxUuwg0w";
activateCerts.Text = "activateCerts";
activateCerts.NavigateUrl = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
}
and this is the one aspx code
<asp:Label runat="server" style="padding-left:23rem;" Text="pls watch this video on How to"></asp:Label>
<asp:HyperLink ID="activateCerts" runat="server"></asp:HyperLink>
but when I click on link I am not able to open a youtube video
This is working for me by setting AutoPostBack=true for dropdpwn ddlPType :
<form id="form1" runat="server">
<div>
<asp:DropDownList runat="server" ID="ddlPType" AutoPostBack="true" OnSelectedIndexChanged="ddlPType_SelectedIndexChanged">
<asp:ListItem Text="Option 1" Selected="True" />
<asp:ListItem Text="Option 2" />
</asp:DropDownList>
<br />
<asp:Label ID="Label1" runat="server" style="padding-left:23rem;" Text="pls watch this video on How to"></asp:Label>
<asp:HyperLink ID="activateCerts" runat="server"></asp:HyperLink>
</div>
</form>
.cs Page :
protected void ddlPType_SelectedIndexChanged(object sender, EventArgs e)
{
int x = ddlPType.SelectedIndex;
if (x == 0)
{
activateCerts.NavigateUrl = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
activateCerts.Text = "activateCerts";
activateCerts.Target = "_blank";
//activateCerts.HRef = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
}
else if (x == 1)
{
//activateCerts.Target = "_blank";
//activateCerts.HRef = "http://www.youtube.com/watch?v=hk3hxUuwg0w";
activateCerts.Text = "activateCerts";
activateCerts.NavigateUrl = "http://www.youtube.com/watch?v=3AYoipyqOkQ";
}
}
For your Dropdownlist named ddlPType, you need to make sure its AutoPostBack is true. You can set it in the Attribute Panel, or using the code:
<asp:DropDownList runat="server" ID="ddlPType" AutoPostBack="true" OnSelectedIndexChanged="ddlPType_SelectedIndexChanged">
By this step you should achieve your goal, but sometimes this is not that simple. You may need to make sure you put your data-bind (if there is) in if (!Page.IsPostBack) in Page_Load.
Also, Dropdownlist will only send data when the data is changed. That is to say, if you get two options sharing the same value, Dropdownlist may not respond you. For example:
if(!IsPostBack)
{
for(int i=0;i<10;i++)this.DropDownList1.Items.Add(new ListItem(i.ToString(),"same_value"));
}
Here comes the most strange situation: you have done all above but it still does not work. Sometimes it happens in IE8. If you use window.showModalDialog() to show DropDownList, submitting will leads you to a new page. You need to add between head tag:
<base target=_self></base>
Hope my experience will do help.

How to create capital letter row for a list of names in an ASP Repeater

I'm using an asp repeater to display a list of names and I want to display the current letter as a type of grouping header, like in an index page.
The data is sorted alphabetically before binding, but i'm finding it difficult to insert the 'A' and 'B' before the names are displayed.
Add a Panel control to your ItemTemplate with visibility set to False. When you are binding the repeater (assuming you are subscribing to the ItemDataBound event), run a check to see if the first letter has changed. If it has, set the panel's visibility to true and print out the letter.
Let me know if you need some example code.
EDIT: EXAMPLE CODE
For clarity sake, "AlphaHeaders" is what we will call the "A", "B", "C" letters that we want to display
aspx code
The Repeater will look like so:
<table>
<asp:Repeater id="rptRepeater" runat="server" OnItemDataBound="rptNames_OnItemDataBound">
<ItemTemplate>
<asp:Panel id="pnlAlphaHeader" runat="server" visible="False">
<tr><td><asp:Label id="lblAlphaHeader" runat="server" /></td></tr>
</asp:Panel>
<tr><td><asp:Label id="lblName" runat="server" /></td></tr>
</ItemTemplate>
</asp:Repeater>
</table>
aspx.cs code
First, you need a variable that holds the current AlphaHeader:
private string _AlphaHeaderCurrent = String.Empty;
Then you will do your work on the repeater's OnItemDataBound event:
protected void rptNames_OnItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if ((e.ItemType==ListItemType.Item) || (e.ItemType==ListItemType.AlternatingItem)) {
string name = e.Item.DataItem("Name").ToString();
//check if the first letter of the current name is new. If it is new, we print out the header
if(!name.StartsWith(this._AlphaHeaderCurrent)) {
this._AlphaHeaderCurrent = name.SubString(1);
((Panel)e.ItemFindControl("pnlAlphaHeader")).Visible = true;
((Label)e.Item.FindControl("lblAlphaHeader")).Text = the._AlphaHeader;
}
((Label)e.Item.FindControl("lblName")).Text = name;
}
}
You sort before you bind.
That is, bind the sorted result set.
Without seeing the values you have, however, it is not possible to tell exactly how to do so.
Update - from your comment, I would say you need to change your binding source to something like Dictionary<string,IList<string>>.
With such a structure, you could bind by key (sorted) and sublist (secondary sort).
You need to sort your data before bind it to the repeater.
You can use nested repeaters (repeater inside repeater). Like category and subcategory.
In first repeater you can list all your names and make a condition starts with A. Then in sub repeater you can show all names. You will also use itemdatabound event to bind second repeater.
<asp:Repeater id="rptFirstLetters" runat="server" OnItemDataBound="rptChars_OnItemDataBound">
<ItemTemplate>
<div>"<%#Eval("letters") %>"
<asp:Repeater id="rptNames" runat="server">
<ItemTemplate>
<%#Eval("names") %>
</ItemTemplate>
</asp:Repeater>
</div> // bind all letters
</ItemTemplate>
Not really a nice way of doing this to be honest, repeaters generally result in ugly code I've found. The hierarchical approach from kad1r is probably the nicest if you can set it up, but there are alternatives, depending on your implementation details; I kind of prefer this in some ways as it keeps the markup very clean, and as I have a non-programmer design guy that is a plus for me.
ASPX:
<%# Page language="C#" Src="test.CODE.cs" Inherits="test_Page" %>
<asp:Repeater ID="TestRepeater" runat="server">
<ItemTemplate>
<asp:PlaceHolder Visible='<%# Eval("IsFirstInGroup") %>' runat="server">
<strong><%# Eval("Initial") %></strong><br/>
</asp:PlaceHolder>
<%# Eval("Name") %><br/>
</ItemTemplate>
</asp:Repeater>
CODE BEHIND:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public class test_Page : Page
{
protected Repeater TestRepeater;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
String[] names = new String[]
{
"Alpha, John",
"Altman, Mary",
"Asher, Cyril",
"Bachman, Turner",
"Beta, Rob",
"Bexman, Norah",
"Clark, Freddy"
};
List<_DispItem> l = new List<_DispItem>();
for (int i = 0; i < names.Length; i++)
l.Add(new _DispItem() { Name = names[i], IsFirstInGroup = (i == 0 || names[i - 1][0] != names[i][0]) });
TestRepeater.DataSource = l;
TestRepeater.DataBind();
}
private class _DispItem
{
public String Name { get; set; }
public String Initial { get { return Name.Substring(0, 1); } }
public bool IsFirstInGroup { get; set; }
}
}

ASP.NET: Access DataItem from an Event Handler

I have a data-bound, templated control, and inside the templated area I create a control with an event handler, like so:
<tnl:DisplayTree ID="DisplayTree1" runat="server" KeyPropertyName="Id"
ParentPropertyName="ParentDemographic" DataSourceID="DemographicObjectSource">
<ItemTemplate>
<asp:CheckBox ID="DemogSelector" runat="server" OnCheckedChanged="DemogSelector_OnCheckedChanged" />
<asp:Label ID="InlineEditLabel" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "Name") %>'></asp:Label>
</ItemTemplate>
</tnl:DisplayTree>
Within the event handler, I would like to be able to detect the Key of the item for which the control was created. For example:
protected void DemogSelector_OnCheckedChanged(object sender, EventArgs e)
{
CheckBox selector = (CheckBox)sender;
DisplayTree.TreeNode treeNode = (DisplayTree.TreeNode)selector.Parent.Parent.Parent.Parent;
Label1.Text += (int)treeNode.Key + ", ";
}
As you can see, this approach requires close knowledge of the hierarchy within my DisplayTree.TreeNode class (i.e. I have to know that sender.Parent.Parent.Parent.Parent is where I'll find the DisplayTree.TreeNode object). I would like to make it a bit more robust, so that if my TreeNode hierarchy changes or something, I can access the key without difficulty. What's the best way for me to make this Key available from within the event handler?
Best way is to add a custom attribute to your checkbox
<asp:CheckBox ID="DemogSelector" runat="server" oncheckedchanged="DemogSelector_CheckedChanged" AutoPostBack="true" key='<%# Eval("Id") %>'/>
And then access it using
string key = (sender as CheckBox).Attributes["key"];
One potential way is to add an extension method to the checkbox, which finds the TreeNode for you, it could be implemented as some loop which recursively searches the parents until the TreeNode is found.
That way you just call selector.FindTreeNode(), of course this would fail on any checkbox called outside of your structure.
The best way is to create your own event arguments class that inherits from EventArgs and expose it as a property there. Since you're using a custom or third-party control, I don't have any advice on how to set the property on the event args. A custom events args would look like this:
public class TreeNodeCheckedChangedEventArgs : EventArgs
{
TreeNodeCheckedChangedEventArgs(int nodeKey)
{
NodeKey = nodeKey;
}
int NodeKey { get; private set; }
}
You can set the value attribute on the checkbox
<asp:CheckBox ID="DemogSelector" runat="server" oncheckedchanged="DemogSelector_CheckedChanged" AutoPostBack="true" value='<%#DataBinder.Eval(Container.DataItem, "Id") %>' />
And retrieve server side
string value = ((CheckBox)sender).Attributes["value"];
I´m using kind of a similar solution as others, adding my code if it helps:
In markup:
<ItemTemplate>
<input type="checkbox"
value="<%# Container.DataItemIndex %>" name="CheckedItems" />
</ItemTemplate>
And in eventhandler:
string checkedItemRowIds = Request.Form["CheckedItems"];

ASP.NET : Possible to create a UserControl that include inside markup content?

I'm trying to achieve something google isn't able to give answer. I'm trying to create an asp.net usercontrol that when I put content into it's open close tag will include it for me to be still able to acess it's content by ID from the Parent. Here is an exemple of what I want to achieve.
Usercontrol:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="ctrlGENE_CollapsiblePanel.ascx.cs"
Inherits="Controls_GenericsControls_ctrlGENE_CollapsiblePanel" %>
<asp:Panel ID="pnlHeader" CssClass="SnapPanelHeader" runat="server">
<h3>
<asp:Literal ID="litTitle" Text='<%# Text %>' runat="server" />
</h3>
<div class="SnapPanelHeader-img">
<img id="imgOpenClose" src="/images/application/close.jpg" alt="" />
</div>
</asp:Panel>
<asp:PlaceHolder runat="server" ID="pnlContent">
// **HERE I WANT TO INCLUDE THE INSIDE MARKUP**
</asp:PlaceHolder>
<act:CollapsiblePanelExtender runat="server" TargetControlID="pnlContent" ImageControlID="imgOpenClose"
ExpandControlID="imgOpenClose" CollapseControlID="imgOpenClose" CollapsedImage="/images/application/open.jpg"
ExpandedImage="/images/application/close.jpg" CollapsedSize="0" TextLabelID="litTitle">
</act:CollapsiblePanelExtender>
Parent Page that include control :
<uc:MyUserControl ID="clpTest" runat="server">
<asp:Literal ID="litText" runat="server" />
</uc:MyUserControl>
Like this I would be able in the Parent.cs file to do :
litText.Text = "Anything";
I know we can achieve something similiar with the ITemplate interface as show here : http://msdn.microsoft.com/en-us/library/36574bf6.aspx
That would look like this:
<uc:MyUserControl ID="clpTest" runat="server">
<ItemTemplate>
<asp:Literal ID="litText" runat="server" />
</ItemTemplate>
</uc:MyUserControl>
But If I do this I wouldn't be able to access the property of litText and the only way I could reach it is with a FindControl, which I want to avoid.
Anyone have a hint on this if I can reach my goal one way or another?
Thank you
Ok I fixed it here is the solution I used :
In MyUserConstrol.ascx file I have put a placeholder where I wanted innerHTML to show :
<asp:PlaceHolder runat="server" ID="plhContent" />
Then in the MyUserControl.ascx.cs file I added those attribute to the class:
[ParseChildren(false)]
[PersistChildren(true)]
And I added to the file this:
public void RegisterUpdatePanel(UpdatePanel panel)
{
MethodInfo m =
(from methods in typeof (ScriptManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
where methods.Name.Equals("System.Web.UI.IScriptManagerInternal.RegisterUpdatePanel")
select methods).First();
m.Invoke(ScriptManager.GetCurrent(Page), new object[] {panel});
}
protected override void CreateChildControls()
{
for (int i = 0; i < Controls.Count; i++)
if (Controls[i] is MyLastControl)
while (i + 2 < Controls.Count)
{
// In cas there is an updatepanel in the control we are moving
// We are registering an event to register the updatepanel
// to the scriptmanager again
SearchUpdatePanel(Controls[i + 2]);
plhContent.Controls.Add(Controls[i + 2]);
}
base.CreateChildControls();
}
private void SearchUpdatePanel(Control control)
{
if (control is UpdatePanel)
control.Unload += updPnl_Unload;
foreach (Control childcontrol in control.Controls)
SearchUpdatePanel(childcontrol);
}
protected void updPnl_Unload(object sender, EventArgs e)
{
RegisterUpdatePanel((UpdatePanel) sender);
}
Note that I named my last control in the ascx file myLastContol to know what was the control before the innerHTML injection since I don't know what I'm receiving. The the procedure basically say loop in the controls in the UserControl, when you will reach the end of UserControl, everything after is innerHTML from parent so take those and move them to the placeholder where I want them.
I hope this will help someone.
Here is some sources I used to achieve my goal :
Registering UpdatePanel
Add a public property in the user control's code behind file. If you need design time support there's more work involved, but for simple scenarios like the one you outlined it should be enough.
Then just access it in the parent page to set the value and read it in the user control and use that value to render whatever you need there.

Categories

Resources