2010-07-30 4 views
2

Je suis en train de développer un contrôle qui permettra au développeur de remplir une collection via le balisage (par exemple, les propriétés décorées avec l'attribut PersistenceMode (PersistenceMode.InnerProperty) J'ai un example de Brian Chavez que plus ou moins fait ce que je veux, mais je veux avoir le Hériter de contrôle de UserControl et contrôle nonProblèmes avec UserControl et Inner Properties

Voici le code que j'ai en vb.net.

AggregateFeeds.ascx.vb

Imports Microsoft.VisualBasic 

<ParseChildren(True)> 
<PersistChildren(False)> 
Public Class AggregateFeeds 
    Inherits UserControl 

    Public Sub New() 
     MyBase.New() 
     Me.Feeds = New RssFeedCollection() 
     Me.Settings = New AggregateSettings() 
    End Sub 

    Private _Feeds As RssFeedCollection 
    Private _Settings As AggregateSettings 

    <PersistenceMode(PersistenceMode.InnerProperty)> 
    Public Property Feeds As RssFeedCollection 
     Get 
      Return _Feeds 
     End Get 
     Private Set(ByVal value As RssFeedCollection) 
      _Feeds = value 
     End Set 
    End Property 

    <PersistenceMode(PersistenceMode.InnerProperty)> 
    Public Property Settings As AggregateSettings 
     Get 
      Return _Settings 
     End Get 
     Private Set(ByVal value As AggregateSettings) 
      _Settings = value 
     End Set 
    End Property 
End Class 

Public Class AggregateSettings 
    Public Property TimeOut As Integer 
    Public Property CacheResults As Boolean 

    Public Sub New() 
     TimeOut = 100 
     CacheResults = True 
    End Sub 

End Class 

Public Class RssFeedCollection 
    Inherits List(Of RssResource) 
End Class 

Public Class RssResource 
    Public Property Url As String = String.Empty 
End Class 

Le fichier ascx ressemble:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="ucAdminTabControl.ascx.vb" Inherits="AggregateFeeds" %> 

Ma page de test est réel simple et ressemble à:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Test.aspx.vb" Inherits="Test" %> 
<%@ Register Src="~/Survey/Controls/ucAdminTabControl.ascx" TagName="AggregateFeeds" TagPrefix="uc" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <uc:AggregateFeeds runat="server" ID="af"> 
      <Settings CacheResults="False" TimeOut="250" /> 
      <Feeds> 
       <uc:RssResource Url="http://test.com" /> 
      </Feeds>   
     </uc:AggregateFeeds>   
    </div> 
    </form> 
</body> 
</html> 

Comme il est maintenant, quand je tente de compiler je reçois une erreur de compilation qui dit simplement objet instance non définie sur une instance d'un objet sur la ligne ci-dessus. Si je l'enlève, la page se charge très bien et l'objet Settings reflète les valeurs du balisage. Pourquoi ai-je des difficultés à remplir la collection correctement?

Répondre

0

Vous devez implémenter votre propre analyseur si vous voulez analyser plusieurs entrées enfants. Vous devez faire de votre classe enfant un contrôle utilisateur et remplacer "AddParsedSubObject". Voici une nouvelle version de votre RssFeedCollection qui acceptera plusieurs chaînes séparées par des retours chariot au lieu des objets RssResource. Vous pouvez rendre l'analyseur plus évolué et analyser XML au lieu de chaînes si vous en avez encore besoin pour le faire.

<ParseChildren(False)> 
<PersistChildren(False)> 
Public Class RssFeedCollection 
    Inherits Web.UI.Control 

    Private _URLs As String() 
    Public ReadOnly Property URLs As String() 
     Get 
      Return _URLs 
     End Get 
    End Property 

    Protected Overrides Sub AddParsedSubObject(ByVal obj As Object) 
     Dim s = DirectCast(obj, LiteralControl).Text.Trim.Replace(" ", "") 'remove spaces 
     Dim separator = New Char() {Microsoft.VisualBasic.vbCr(0)} 

     _URLs = s.Split(separator, System.StringSplitOptions.RemoveEmptyEntries) 

     MyBase.AddParsedSubObject(obj) 
    End Sub 
End Class 
+0

Merci pour votre réponse. Cela peut fonctionner mais je sais que l'exemple sur le site de Brian Chavez fonctionne comme prévu et n'implique pas cela et je voudrais éviter de faire de RssFeedCollection un UserControl quand il est vraiment mieux adapté comme une simple collection d'objets simples –

+0

@EDIT: Il n'a qu'à hériter de Control, mon erreur. –

+0

J'ai ajouté une nouvelle solution. L'ancien est toujours utile pour mettre en évidence l'utilisation de la méthode "AddParsedSubObject", mais le nouveau vous permet d'utiliser correctement les attributs. –

0

Voici une solution plus simple. J'ai supprimé votre pour cet exemple; ce code devrait fonctionner comme avant.

Voici l'ASPX que j'utilise.

<uc:AggregateFeeds runat="server" ID="af"> 
     <Feeds> 
      <RssResource Url="Test1" /> 
      <RssResource Url="Test2" /> 
      <RssResource Url="Test3" /> 
     </Feeds> 
    </uc:AggregateFeeds> 

Voici le code de contrôle de l'utilisateur.

Partial Class AggregateFeeds 
    Inherits System.Web.UI.UserControl 

    Private _Feeds As New MyFeedsClass(Me) 

    <PersistenceMode(PersistenceMode.InnerProperty)> 
    Public ReadOnly Property Feeds As MyFeedsClass 
     Get 
      Return _Feeds 
     End Get 
    End Property 
End Class 

Public Class MyFeedsClass 
    Inherits ControlCollection 

    Sub New(ByVal owner As Control) 
     MyBase.New(owner) 
    End Sub 

    Public Overrides Sub Add(ByVal child As System.Web.UI.Control) 
     MyBase.Add(New Feed(child)) 
    End Sub 
End Class 


Public Class Feed 
    Inherits HtmlGenericControl 

    Sub New(ByVal GenericControl As HtmlGenericControl) 
     MyBase.New() 
     Me.Url = GenericControl.Attributes("Url") 
    End Sub 

    Public Property Url As String = String.Empty 

    Public Overrides Function ToString() As String 
     Return Me.Url 
    End Function 
End Class 

Cela fonctionne en supposant que chaque contrôle enfant est un contrôle générique html. N'utilisez pas <uc dans le contrôle enfant afin qu'il ne tente pas de correspondre à une classe réelle.