|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Required multiple instances of a UserControl loaded at runtimeI need to access multiple instances of the same UserControl dynamically. I can successful do this with one control but I'm not sure how I can assign multiple instances to a Repeater at runtime. This is what I have so far protected void Page_Init(object sender, EventArgs e) { // load the account finder control _accountFinder = (AccountFinder)LoadControl("~/Controls/AccountFinder.ascx"); } //This is called multiple times by a Repeater control //I need to be able to add a new instance of the control if the PlaceHolder is visible protected void phIndividualsFinder_Load(object sender, EventArgs e) { PlaceHolder phIndividualsFinder = (PlaceHolder)sender; // made visible by the click event on a previous postback if (phIndividualsFinder.Visible == true) { phIndividualsFinder.Controls.Add(_accountFinder); } } What is the correct way of achieving this? Many thanks Andrew Hello Andrew,
Do you mean you want to programmatically add an ascx usercontrol into each Item of the repeater control? If so, I think you can use the Repeater.ItemCreated event. This is because for dynamic control, we need to create and add it in each page request, and for Repeater control, those items are generated through Databinding, and the only means to customize each repeater item's control collection is in the "ItemCreated" event because this event is fired in each page request. e.g. =======aspx======= ............................... <asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" OnItemCreated="Repeater1_ItemCreated"> <ItemTemplate> <br /><hr /><br /> <asp:PlaceHolder ID="holder1" runat="server"></asp:PlaceHolder> </ItemTemplate> </asp:Repeater> </div> </form> </body> </html> ========code behind========= protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { PlaceHolder holder = e.Item.FindControl("holder1") as PlaceHolder; if (holder != null) { Control uc = Page.LoadControl("~/uc/WebUserControl.ascx"); holder.Controls.Add(uc); } } } ==================== Hope this helps. Sincerely, Steven Cheng Microsoft MSDN Online Support Lead ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. Hi Steven
That helps, thanks. I have another related question. I have a repeater protected void repFilterParamsGroups_ItemDataBound(Object Sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { DataRowView row = (DataRowView)e.Item.DataItem; // bind data byte val = (byte)row["OrGroup"])) } } There are a few nested controls under each repeater Item. I need to access the row["OrGroup"] value from a custom event which fires from a User Control. I've been trying to access this value but I can't find it private void accountFinder_AccountIdSelected(object sender, EventArgs e) { AccountFinder accountFinder = (AccountFinder)sender; // This doesn't work Trace.Warn(accountFinder.Parent.Parent.Parent.Parent.Controls[1].ID); } Is there a neater/suggested way to locate the value of the accountFinder's ancestor? Thanks Andrew Hello Andrew,
Thanks for your reply. For your further questions, here are my understanding and suggestion: the "e.Item.DataItem" object refer to the current item from databound datasource, and this is only available during databinding period. And in your usercontrol's custom event handler (or any other place durign control lifecycle), this propety is not available, you need to persist the value in some certain place so that the usercontrol can access it later. So far what I've got are the following two means to persist the value: 1. directly use databinding expression in ascx usercontrol to bind the value to a sub control in usercontrol. e.g. ================ <%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="uc_WebUserControl" %> ........................ <asp:Label ID="lblData" runat="server" Text='<%# Eval("CategoryName") %>' Visible="false"></asp:Label> ================ When you add usercontrol into any databound context(in repeater, datalist...), it can automatically join the databinding context and get the value from each DataItem 2. You can also define a custom property on the usercontrol so that you can persist the data from DataSource Item into this property on usercontrol. Later, the usercontrol's method or event can access this property to get the data. e.g. =========usercontrol code behind========= public partial class uc_WebUserControl : System.Web.UI.UserControl { public string DataText { get { if (ViewState["_datatext"] != null) { return ViewState["_datatext"] as string; } return "default data text"; } set { TrackViewState(); ViewState["_datatext"] = value; } } .................. protected void Button1_Click(object sender, EventArgs e) { Label1.Text = DataText; } } ======================== And in repeater's databound code, you can programmatically assign this value: =================== protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { PlaceHolder holder = e.Item.FindControl("holder1") as PlaceHolder; if (holder != null) { Control uc = Page.LoadControl("~/uc/WebUserControl.ascx"); uc_WebUserControl wuc = uc as uc_WebUserControl; wuc.DataText = DataBinder.Eval(e.Item.DataItem, "CategoryID", "{0}"); holder.Controls.Add(uc); } } } =============================== #Note that since ASP.NET page/usercontrol use partial class, to reference the actual type of the usercontrol in page, you need to explicitly reference it in Page(through @page directive) .e.g. ================ <%@ Page ...................%> <%@ Reference VirtualPath="~/uc/WebUserControl.ascx" %> ............... ================== Hope this helps. If there is anything unclear, please feel free to let me know. Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights. Hi Steven
Thanks for the information. I have another question. I am currently loading the user control when a button onclick event fires and also in a Placeholder Load event in the right conditions. This works fine for me. How can I access the DataItem value from the ItemCreated method? I think I need to store the values in viewstate for each DataItem of each RepeaterItem so I can access these values in the Load and OnClick events (also without rebinding). What would be the appropriate way? Thanks Andrew Show quoteHide quote "Steven Cheng[MSFT]" <stch***@online.microsoft.com> wrote in message news:FQ%23EPz0IHHA.2080@TK2MSFTNGHUB02.phx.gbl... > Hello Andrew, > > Thanks for your reply. > > For your further questions, here are my understanding and suggestion: > > the "e.Item.DataItem" object refer to the current item from databound > datasource, and this is only available during databinding period. And in > your usercontrol's custom event handler (or any other place durign control > lifecycle), this propety is not available, you need to persist the value > in > some certain place so that the usercontrol can access it later. > > So far what I've got are the following two means to persist the value: > > 1. directly use databinding expression in ascx usercontrol to bind the > value to a sub control in usercontrol. e.g. > > ================ > <%@ Control Language="C#" AutoEventWireup="true" > CodeFile="WebUserControl.ascx.cs" Inherits="uc_WebUserControl" %> > ....................... > <asp:Label ID="lblData" runat="server" Text='<%# Eval("CategoryName") %>' > Visible="false"></asp:Label> > ================ > > When you add usercontrol into any databound context(in repeater, > datalist...), it can automatically join the databinding context and get > the > value from each DataItem > > > 2. You can also define a custom property on the usercontrol so that you > can > persist the data from DataSource Item into this property on usercontrol. > Later, the usercontrol's method or event can access this property to get > the data. e.g. > > =========usercontrol code behind========= > public partial class uc_WebUserControl : System.Web.UI.UserControl > { > public string DataText > { > get > { > if (ViewState["_datatext"] != null) > { > return ViewState["_datatext"] as string; > } > return "default data text"; > } > > set > { > TrackViewState(); > ViewState["_datatext"] = value; > } > } > > ................. > > protected void Button1_Click(object sender, EventArgs e) > { > Label1.Text = DataText; > } > } > ======================== > > And in repeater's databound code, you can programmatically assign this > value: > > =================== > protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs > e) > { > if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == > ListItemType.AlternatingItem) > { > PlaceHolder holder = e.Item.FindControl("holder1") as > PlaceHolder; > > if (holder != null) > { > Control uc = Page.LoadControl("~/uc/WebUserControl.ascx"); > > uc_WebUserControl wuc = uc as uc_WebUserControl; > wuc.DataText = DataBinder.Eval(e.Item.DataItem, > "CategoryID", "{0}"); > > holder.Controls.Add(uc); > } > } > } > =============================== > > #Note that since ASP.NET page/usercontrol use partial class, to reference > the actual type of the usercontrol in page, you need to explicitly > reference it in Page(through @page directive) .e.g. > > ================ > <%@ Page ...................%> > <%@ Reference VirtualPath="~/uc/WebUserControl.ascx" %> > > .............. > ================== > > Hope this helps. If there is anything unclear, please feel free to let me > know. > > Sincerely, > > Steven Cheng > > Microsoft MSDN Online Support Lead > > > This posting is provided "AS IS" with no warranties, and confers no > rights. > Thanks for your reply Andrew,
Yes, you're right. You have to store the value (from DataItem) in some place since DataItem is only available during databinding context and in your Button_Click or placeholder's load event, it is not always supposed to work. There are two common approachs you can consider to store the value: ** during databinding context, store those data you need later in ViewState (you also need to put additional info to identify which row does each data belongs to) ** you can add an additional hidden control (<input type="hidden" .../> or a hidden Label) in each Repeater Row and you can use databinding to store the data you need in those hidden control. No matter what means you use, the purpose is prestore the data during databinding and the storage should be accessible at sequential time when you need it. Hope this helps. Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights.
Other interesting topics
No open/save prompt
Wizard.FinishButtonClick - launch browser AND redirect How to get GridView row from DataKey? Return Values from Popup to UserControl How can I send shell-commands to the web-server in webcontrols? Keeping 2 user controls of the same class synced How to close multiple web pages data field - change true/false to Yes/No can't remove listitem from ddl in loop Item has already been added. Key in dictionary |
|||||||||||||||||||||||