ASP.NET维护具有集合项

时间:2015-08-11 16:55:02

标签: asp.net generics collections custom-controls state

有趣。我有一个带有QuickContacts集合的控件Contacts。当我声明类型为Contacts的{​​{1}}时,它可以正常工作,但是当使用List<Contact>这是一个实现ContactsList<Contact>的Generic时,它会给出“Parser Error:Type'Controls.ContactList' 1 [[Controls.Contact,Controls,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]'没有名为'Contact'的公共属性。“ 在这里,此代码与IList<T>

完美配合
List<Contact>

我想提供一个维护状态的[DefaultProperty("Contacts"), ParseChildren(true, "Contacts"), ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")] public class QuickContacts : WebControl { private List<Contact> contactsList; [Category("Behavior"), Description("The contacts collection."), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerDefaultProperty)] public List<Contact> Contacts { get { if (contactsList == null) { contactsList = new List<Contact>(); } return contactsList; } } 集合,因此我使用Contacts替换了实现List<Contacts>的自定义ContactsList。使用IList<T>, IStateManager代替IList<T>时,它不起作用。这是

List<T>

然后我用它如下:

public class ContactList<T> : IList<T>, IStateManager
{

“Parser Error:Type'Controls.ContactList'1 [[Controls.Contact,Controls,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]'没有名为'Contact'的公共属性。”
[DefaultProperty("Contacts"), ParseChildren(true, "Contacts"), ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")] public class QuickContacts : WebControl { private ContactList<Contact> contactsList; [Category("Behavior"), Description("The contacts collection."), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerDefaultProperty)] public ContactList<Contact> Contacts { get { if (contactsList == null) { contactsList = new ContactList<Contact>(); } return contactsList; } }

处的分析器错误
<cc1:Contact Name=

我阅读了很多关于<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server"> <cc1:QuickContacts ID="QuickContacts1" runat="server" BorderStyle="Solid" BorderWidth="1px"> <cc1:Contact Name="someone" Email="someone@example.com" Phone="(555) 555-0100" /> vs List<T>的帖子,但仍然没有回答这个问题。 IList<T>与实现List<T>的类之间有什么区别导致此错误?

1 个答案:

答案 0 :(得分:0)

以下是在Microsoft http://referencesource.microsoft.com

审核List<T>时的答案
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{

它也实现了System.Collections.IList。这就是重点。

这是完整的工作代码。

[DefaultProperty("Contacts"),
ParseChildren(true, ChildrenAsProperties = true, DefaultProperty = "Contacts"),
ToolboxData("<{0}:QuickContacts runat=server></{0}:QuickContacts>")]
public class QuickContacts : WebControl
{
    private StateManagedCollection<Contact> contactsList;

    [Category("Behavior"),
    Description("The contacts collection."),
    DesignerSerializationVisibility(
        DesignerSerializationVisibility.Content),
    PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public StateManagedCollection<Contact> Contacts
    {
        get
        {
            if (contactsList == null)
            {
                contactsList = new StateManagedCollection<Contact>();
            }
            return contactsList;
        }
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {

        Table t = CreateContactsTable();
        if (t != null)
        {
            t.RenderControl(writer);
        }
    }

    private Table CreateContactsTable()
    {
        Table t = null;

        if (contactsList != null && contactsList.Count > 0)
        {
            t = new Table();

            foreach (Contact item in contactsList)
            {
                Contact aContact = item as Contact;

                if (aContact != null)
                {
                    TableRow row = new TableRow();

                    TableCell c1 = new TableCell();
                    c1.Text = aContact.Name;
                    row.Controls.Add(c1);

                    TableCell c2 = new TableCell();
                    c2.Text = aContact.Email;
                    row.Controls.Add(c2);

                    TableCell c3 = new TableCell();
                    c3.Text = aContact.Phone;
                    row.Controls.Add(c3);

                    t.Controls.Add(row);
                }
            }
        }

        return t;
    }

    protected override void LoadViewState(object savedState)
    {
        if (savedState != null)
        {
            Pair p = savedState as Pair;
            base.LoadViewState(p.First);
            contactsList.LoadViewState(p.Second);
        }
    }

    protected override object SaveViewState()
    {
        Pair p = new Pair(base.SaveViewState(), contactsList.SaveViewState());
        return p;
    }

    protected override void TrackViewState()
    {
        base.TrackViewState();
        contactsList.TrackViewState();
    }
}

这是StateManagedCollection

    public class StateManagedCollection<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>, IStateManager
        where T : StateManagedClass, new()
{
    private List<T> lst = default(List<T>);
    private Boolean isTrackingViewState = default(Boolean);
    private Boolean saveAll = default(Boolean);

    public StateManagedCollection()
    {
        lst = new List<T>();
        isTrackingViewState = false;
        saveAll = false;
    }

    public void SetMarked()
    {
        for (int i = 0; i < lst.Count; i++)
        {
            lst[i].SetMarked();
        }
    }

    public bool IsTrackingViewState
    {
        get { return isTrackingViewState; }
    }

    public void LoadViewState(object state)
    {
        if (state != null)
        {

            if (state is List<Object>)
            {
                // all items were saved

                List<Object> allItems = (List<Object>)state;
                saveAll = true;
                Int32 count = lst.Count;
                for (int i = 0; i < allItems.Count; i++)
                {
                    if (i < count)
                        lst[i].LoadViewState(allItems[i]);
                    else
                    {
                        T item = new T();
                        item.LoadViewState(allItems[i]);
                        lst.Add(item);
                    }
                }
            }
            else if (state is Dictionary<Int32, Object>)
            {
                Dictionary<Int32, Object> changedItems = (Dictionary<Int32, Object>)state;
                foreach (KeyValuePair<Int32, Object> item in changedItems)
                {
                    if (item.Key < lst.Count)
                        lst[item.Key].LoadViewState(item.Value);
                }
            }
        }
    }

    public object SaveViewState()
    {
        if (saveAll)
        {
            List<Object> allItems = new List<Object>();
            foreach (var item in lst)
            {
                item.SetMarked();
                allItems.Add(item.SaveViewState());
            }
            return allItems;
        }
        else
        {
            Dictionary<Int32, Object> changedItems = new Dictionary<Int32, Object>();
            for (int i = 0; i < lst.Count; i++)
            {
                Object state = lst[i].SaveViewState();
                if (state != null)
                {
                    changedItems.Add(i, state);
                }
            }
            return changedItems;
        }
    }

    public void TrackViewState()
    {
        isTrackingViewState = true;
        for (int i = 0; i < lst.Count; i++)
        {
            lst[i].TrackViewState();
        }
    }

    public int IndexOf(T item)
    {
        return lst.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        lst.Insert(index, item);
        if (isTrackingViewState)
            saveAll = true;
    }

    public void RemoveAt(int index)
    {
        lst.RemoveAt(index);
        if (isTrackingViewState)
            saveAll = true;
    }

    public T this[int index]
    {
        get
        {
            return lst[index];
        }
        set
        {
            lst[index] = value;
        }
    }

    public void Add(T item)
    {
        lst.Add(item);
        if (isTrackingViewState)
            saveAll = true;
    }

    public void Clear()
    {
        lst.Clear();
        if (isTrackingViewState)
            saveAll = true;
    }

    public bool Contains(T item)
    {
        return lst.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        lst.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return lst.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        Boolean rslt = lst.Remove(item);
        if (isTrackingViewState)
            saveAll = true;
        return rslt;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return lst.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public int Add(object value)
    {
        Add((T)value);
        return Count - 1;
    }

    public bool Contains(object value)
    {
        return Contains((T)value);
    }

    public int IndexOf(object value)
    {
        return IndexOf((T)value);
    }

    public void Insert(int index, object value)
    {
        Insert(index, (T)value);
    }

    public bool IsFixedSize
    {
        get { return ((IList)lst).IsFixedSize; }
    }

    public void Remove(object value)
    {
        Remove((T)value);
    }

    object IList.this[int index]
    {
        get
        {
            return lst[index];
        }
        set
        {
            lst[index] = (T)value;
        }
    }

    public void CopyTo(Array array, int index)
    {
        CopyTo((T[])array, index);
    }

    public bool IsSynchronized
    {
        get { return ((ICollection)lst).IsSynchronized; }
    }

    public object SyncRoot
    {
        get { return ((ICollection)lst).SyncRoot; }
    }
}

StateManagedClass

public abstract class StateManagedClass : IStateManager
{
    private Boolean isTrackingViewState = default(Boolean);
    private StateBag viewState = default(StateBag);

    public StateManagedClass()
    {
        isTrackingViewState = false;
        viewState = new StateBag(false);
    }

    public virtual StateBag ViewState
    {
        get
        {
            return viewState;
        }
    }

    public bool IsTrackingViewState
    {
        get { return isTrackingViewState; }
    }

    public void LoadViewState(object state)
    {
        if (state != default(object))
        {
            ((IStateManager)viewState).LoadViewState(state);
        }
    }

    public object SaveViewState()
    {
        Object savedState = default(Object);

        if (viewState != null)
        {
            savedState =
                ((IStateManager)viewState).SaveViewState();
        }

        return savedState;
    }

    public void TrackViewState()
    {
        isTrackingViewState = true;

        if (viewState != default(StateBag))
        {
            ((IStateManager)viewState).TrackViewState();
        }
    }

    public void SetMarked()
    {
        viewState.SetDirty(true);
    }
}

和Contact类

public class Contact : StateManagedClass 
{
    [
    Category("Behavior"),
    DefaultValue(""),
    Description("Name of contact"),
    NotifyParentProperty(true)
    ]
    public String Name
    {
        get
        {
            Object s = ViewState["Name"];
            return (s == null) ? String.Empty : (String)s;
        }
        set
        {
            ViewState["Name"] = value;
        }
    }

    [
    Category("Behavior"),
    DefaultValue(""),
    Description("Email address of contact"),
    NotifyParentProperty(true)
    ]
    public String Email
    {
        get
        {
            Object s = ViewState["Email"];
            return (s == null) ? String.Empty : (String)s;
        }
        set
        {
            ViewState["Email"] = value;
        }
    }

    [
    Category("Behavior"),
    DefaultValue(""),
    Description("Phone number of contact"),
    NotifyParentProperty(true)
    ]
    public String Phone
    {
        get
        {
            Object s = ViewState["Phone"];
            return (s == null) ? String.Empty : (String)s;
        }
        set
        {
            ViewState["Phone"] = value;
        }
    }

}

测试控件:

<%@ Page Title="" Language="C#" MasterPageFile="~/RTL.Master" AutoEventWireup="true" CodeBehind="WebForm15.aspx.cs" Inherits="Controls.WebForm15" %>

<%@ Register Assembly="Controls" Namespace="Controls" TagPrefix="cc1" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server">
    <cc1:QuickContacts ID="QuickContacts1" runat="server" BorderStyle="Solid" BorderWidth="1px">
        <cc1:Contact Name="someone" Email="someone@example.com"
            Phone="(555) 555-0100" />
        <cc1:Contact Name="jae" Email="jae@fourthcoffee.com"
            Phone="(555) 555-0101" />
        <cc1:Contact Name="lene" Email="lene@contoso.com"
            Phone="(555) 555-0102" />
    </cc1:QuickContacts>
    <br />
    <asp:Button runat="server" ID="Button1" Text="Add" OnClick="Button1_Click"></asp:Button>
    <asp:Button runat="server" Text="Refresh"></asp:Button>
    <br />
    <br />
    <asp:HyperLink ID="HyperLink1" NavigateUrl="~/WebForm15.aspx"
        runat="server">
    Reload Page</asp:HyperLink>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="script" runat="server">
</asp:Content>

代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Controls
{
    public partial class WebForm15 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            SkolaControlsWorkings.Controls.Contact contact = new SkolaControlsWorkings.Controls.Contact();
            contact.Name = "Name";
            contact.Email = "Email@mai.com";
            contact.Phone = "(111) 111-1111";
            QuickContacts1.Contacts.Add(contact);
            Button1.Visible = false;
        }
    }
}

现在您可以看到按“添加”按钮如何将新的联系人项目添加到列表中,以及如何通过页面回发来维护新添加的联系人。
这应该是一个完整的工作示例,玩得开心 这是MSDN原始示例Web Control Collection Property Example