Проблемы с UserControl и внутренними свойствами - PullRequest
2 голосов
/ 30 июля 2010

Я пытаюсь разработать элемент управления, который позволит разработчику заполнять коллекцию с помощью разметки (например, свойства, украшенные атрибутом PersistenceMode (PersistenceMode.InnerProperty). У меня есть пример из Брайан Чавес , что более или менее делает то, что я хочу, но я хочу, чтобы элемент управления наследовал от UserControl, а не от элемента Control.

Вот код, который я имею в 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

Файл ascx выглядит так:

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

Моя тестовая страница очень проста и выглядит следующим образом:

<%@ 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>

Как и сейчас, когда я пытаюсь скомпилировать, я получаю ошибку компилятора, которая просто говорит, что экземпляр объекта не установлен в качестве экземпляра объекта в строке выше. Если я достану его, страница загружается очень хорошо, и объект настроек отражает значения в разметке. Почему у меня возникают проблемы с правильным заполнением коллекции?

Ответы [ 2 ]

0 голосов
/ 31 июля 2010

Вот более простое решение. Я удалил ваш AggregateSettings для этого примера; этот код должен работать так же, как и раньше.

Вот ASPX, который я использую.

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

Вот код контроля пользователя.

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

Это работает при условии, что каждый дочерний элемент управления является универсальным элементом управления html. Не используйте <uc в дочернем элементе управления, чтобы он не пытался сопоставить фактический класс.

0 голосов
/ 30 июля 2010

Вы должны реализовать свой собственный анализатор, если вы хотите проанализировать несколько дочерних записей. Вы должны сделать свой дочерний класс пользовательским элементом управления и переопределить «AddParsedSubObject». Вот новая версия вашей коллекции RssFeedCollection, которая будет принимать несколько строк, разделенных возвратом каретки, вместо объектов RssResource. Вы можете сделать синтаксический анализатор более продвинутым и анализировать XML вместо строк, если вам все еще нужно это сделать.

<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
...