Ajouter dynamiquement un contrôle utilisateur à un répéteur
J'ai une classe (Maclasse), ce qui représente une hiérarchie, de sorte que la classe a une propriété qui est une collection de MyClass. Maclasse a aussi un titre de propriété
Pour l'afficher sur une page web, j'ai été en espérant pour créer un contrôle utilisateur qui a un répéteur. Dans le modèle d'élément, j'aurais littérale pour afficher le titre de propriété, et sur la ItemCreated cas de la répétition, je voudrais créer une nouvelle instance de l'objet usercontrol, et l'ajouter dans l'élément courant dans le relais.
Mon problème est que, lorsque l'événement Page_Load dans le usercontrol incendies, si le contrôle a été ajouté de manière dynamique, la repMyClass répéteur poroperty est nulle, même si je l'appelle EnsureChildControls. Suis-je manqué quelque chose? Si je créer un répéteur et baisse mon userctonrol dans le modèle d'élément, il fonctionne très bien. Mon ne puis-je pas obtenir que cela fonctionne de façon dynamique?
De Contrôle De L'Utilisateur:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="MyControl" %>
Items:<br/>
<asp:Repeater ID="repMyClass" runat="server" EnableViewState="false"
OnItemCreated="repMenuItems_ItemCreated">
<HeaderTemplate><ul><HeaderTemplate>
<ItemTemplate>
<li><%# Eval("Title") %>
<div><asp:PlaceHolder ID="SubItemPlaceholder" runat="server" /></div>
</li></ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
De Contrôle De L'Utilisateur Code:
public partial class MyControl: System.Web.UI.UserControl
{
public IEnumerable<MyClass> ChildItems { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
this.repMyClass.DataSource = ChildItems;
this.repMyClass.DataBind();
}
protected void repMenuItems_ItemCreated(object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
//Get the MyClass instance for this repeater item
MyClass mcCurrent = (MyClass)e.Item.DataItem;
//If the MyClass instance has child instances
if (mcCurrent.Children != null && mcCurrent.Children.Length > 0)
{
//Add a new user control and set it's property so it can bind
PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder");
MyControl ctl = (MyControl)Page.LoadControl(typeof(MyControl),new object[] {});
ctl.ChildItems = mcCurrent.Children;
ph.Controls.Add(ctl);
}
}
}
}
OriginalL'auteur Jeremy | 2011-10-05
Vous devez vous connecter pour publier un commentaire.
Je l'avais fait il y a longtemps pour la création de imbriquée de rapports à l'aide des Accordéons.
Dans l'Index, quand vous voulez pour ajouter dynamiquement des instances de Contrôle Utilisateur:
Remarque:
Dans le Contrôle de l'Utilisateur, vous devez ajouter le "ClassName" dans la déclaration de la balise
Aussi, toutes les propriétés que vous souhaitez exposer lors de la création d'instances de façon dynamique, vous déclarer comme suit:
Donc, si vous voulez forcer une valeur lors de la création de "repMyClass", vous pouvez le définir comme une propriété et d'attribuer quelque valeur que ce soit que vous voulez, il programmaticaly.
Bien sûr vous pouvez. Il suffit de créer une propriété de type de répéteur. Vous pouvez ensuite y accéder, instantize, faites tout ce que vous voulez avec elle. Veuillez préciser - selon moi, vous devriez avoir une propriété publique dans le contrôle UserControl, dans le Chargement de la Page de l'objet UserControl vous devriez être en utilisant que les biens publics pour lier les données à la répétition. Est-ce exact?
OriginalL'auteur Varun Vohra
Vous pouvez faire un autre constructeur dans le contrôle qui prend la propriété que vous voulez et de les utiliser dans l'événement load, puis passer dans le vide de l'objet de tableau dans LoadControl ().
Une autre approche est de tirer de la logique dans le setter de la propriété au lieu de dans l'événement Load de la commande, étant donné que c'est essentiellement la charge réelle ici et déclenche une seule fois par demande et par contrôle si je comprends bien.
Une autre approche est de ne pas le charger dynamiquement, comme tous.
à l'intérieur de votre modèle d'élément que vous pouvez avoir quelque chose comme:
Mise à jour
Encore une approche qui ne m'a jamais donné des erreurs avec les contrôles enfants dans les contrôles de l'utilisateur à l'intérieur de répéteurs ou de la page du cycle de vie, est d'utiliser l'Élément Lié aux Données de l'événement au lieu de l'Élément Créé.
En fait, quand j'y pense maintenant, votre code ne doit pas parce que l'e.De l'élément.DataItem n'a pas été lié à encore.
Essayer de faire changer le cas de ItemDataBound et voir si cela fonctionne.
.
J'ai toujours bien vous recommandons d'inclure le contrôle de l'élément de marquage, de contrôle et de la visibilité de la commande dans le cas (maintenant ItemDataBound). Vous pouvez consulter le contrôle par quelque chose comme
e.Item.FindControl("ControlId") as MyControl
(renvoie null si elle ne trouve pas dans l'article courant).Essayez de combiner les deux, ou au moins changer les données liée à la place de créé, et voyons voir...
La théorie est que vous ne devriez pas avoir à utiliser la charge, utilisez le setter de la place. Une autre alternative est dans la réponse de mise à jour, que l'on pourrait résoudre le problème. Je pense que le problème est l'événement utilisé, ce qui a une très bonne probabilité d'être la question.
OriginalL'auteur Meligy