C# 将动态控件插入控件集合的中间

C# 将动态控件插入控件集合的中间,c#,asp.net,user-controls,dynamic-controls,C#,Asp.net,User Controls,Dynamic Controls,这是我的第一篇帖子!我非常绝望,所以我要超越我的标准谷歌搜索。我相信这是一个高级或专家级的.NET问题 问题是我构建了一个.NETWeb应用程序,它需要能够将用户控件动态插入列表的中间。我对动态控件非常熟悉,只要它们只需要添加到列表的末尾即可(即:我熟悉这样的文章:)。但是,如果我需要在控件集合的前面或中间的某个地方添加一个USER控件,则由于控件的UniqueID被抛出,我几乎失去了。 作为一个简化的示例,假设我有一个面板,其中添加了一个名为MyControl.ascx的用户控件列表。我还有一

这是我的第一篇帖子!我非常绝望,所以我要超越我的标准谷歌搜索。我相信这是一个高级或专家级的.NET问题

问题是我构建了一个.NETWeb应用程序,它需要能够将用户控件动态插入列表的中间。我对动态控件非常熟悉,只要它们只需要添加到列表的末尾即可(即:我熟悉这样的文章:)。但是,如果我需要在控件集合的前面或中间的某个地方添加一个USER控件,则由于控件的UniqueID被抛出,我几乎失去了。

作为一个简化的示例,假设我有一个面板,其中添加了一个名为MyControl.ascx的用户控件列表。我还有一些可能在页面上触发的事件,需要将MyControl.ascx动态插入面板控件集合的指定索引中。我还需要订阅MyControl.ascx上的一个或多个事件。这意味着需要在触发这些控件上的事件之前加载这些控件,否则它们将不会触发。如果你不知道我指的是什么,那么我要么把问题写得很糟糕,要么这个问题对你来说太难:)

下面是一些C#伪代码来演示这个问题。问题是Controls.AddAt(index,control)方法没有相应地调整控件的UniqueID值。例如,在控件集合中考虑以下控件:

无论我是否在编写直接依赖于UniqueID的代码,.NET间接地使用UniqueID将在上一次回发时触发的事件与在新回发时加载的控件链接在一起。以我前面的例子:

在初始
页面加载时(Page.IsPostback==false)

因此,如果我在控件中单击一个linkbutton,Value==value0,UniqueID==ctl03,那么控件的顺序将如下所示,并且UniqueID将不是我想要的顺序。这将导致单击事件附加到错误的控件:

<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl00</td>
    <td>value0  <== the control i wanted to throw the event</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl01</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl02</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>ctl03</td>
    <td>value3  <== the actual control to which the event is attached</td>
  </tr>
</table>

控制指标
独一无二的
价值
0
ctl00

value0要使自动编号起作用,您需要在每次回发时以相同的顺序将控件添加到面板中。显然,在回发中,控件必须分配其唯一的ID,否则您将无法获得控件事件

UniqueID
在首次使用时初始化为
Control.ID
*属性的值。如您所观察到的,如果未设置该属性,它将自动生成为
ctlxx
。分配后,控件的
唯一ID
为只读

因此,如果您有某种形式的主键,则可以在基于该主键创建控件时设置控件的
ID
属性。当页面加载其状态时,
UniqueID
将被设置为该值

  • 脚注:
    UniqueID
    属性实际上是命名容器前缀和
    ID
    属性的组合

请在页面指令中使用以下属性

MaintainScrollPositionOnPostback = true

我相信这会有所帮助。

现在,你的做法是错误的,你是在解释你的问题,而不是解释你想完成什么。在这方面存在差异,这使得很难提出更好的解决特定问题的方法(有时是正确的方法)。编辑你的问题!谢谢你的回复,阳光。一旦我将UniqueID添加到myPanel中,它就会被设置。问题是,在调用“SomeOtherControl\u ClickInsert”时,这些控件已经在面板上,并且分配了唯一ID。当我要插入我的控制时已经太晚了。我真的很讨厌这个300字符的限制。无论如何,我知道UniqueID是父控件和页以及控件集合中控件的索引的组合。我只是不知道如何把控件放在集合中间,并钩住正确的事件……如果单击某个动态控件,则在回发时钩住右侧事件。你能再详细一点吗?我的问题可能措辞不好,我不确定。哦,等等。。。我明白你在说什么了!当我将control.ID添加到面板时,我还没有设置它——这就是为什么它要设置自己的uniqueID。因为我确实有一个主键值,所以我应该能够将ID设置为该键。我会好好玩玩的,很快就会回来的。谢谢好吧,你真是个天才。这正是问题所在!在将control.ID添加到另一个控件集合之前,我没有设置它,因此.NET可以随意使用自己的计数器。当我将ID分配给自己的主键值时,问题就解决了。谢谢阳光!!
<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl00</td>
    <td>value0  <== the control i wanted to throw the event</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl01</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl02</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>ctl03</td>
    <td>value3  <== the actual control to which the event is attached</td>
  </tr>
</table>
// on init i just need to pull the records from the DB, turn them
// into a MyControl.ascx, and then add them to my panel
protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    // get my List<SomethingFromDB> ordered by value and iterate through, 
    // adding controls to the control collection
    List<SomethingFromDB> myList = remoteService.GetSomeListFromTheDB();
    foreach(SomethingFromDB something in List<SomethingFromDB>)
    {
        // load a new MyControl.ascx
        MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");
        // populate the values of myControl with the "something"
        this.populateMyControl(something);
        // dynamically add the control to my panel
        this.myPanel.Add(myControl);     
        // subscribe to event
        myControl.SomeArbitraryEvent += new EventHandler(MyArbitraryHandler);
    }

    // This event gets fired by a magical control on the page and passes a 
    // new SomethingFromDB which needs to be inserted into the DB and then 
    // dynamically inserted into the Controls collection at the specified index
    private void SomeOtherControl_ClickInsert(object sender, MyControlEventArgs e)
    {
        // insert this record into the DB             
        remoteService.InsertIntoDB(e.SomethingFromDB);     
        // dynamically load this control
        MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");
        // get the index into which we will be inserting this control
        int index = e.NewIndex;                   
        //dynamically add the control to my panel at the specified index.
        // THIS DOES NOT ADJUST THE UNIQUEID VALUES ACCORDINGLY
        // AND IS THE SOURCE OF MY PROBLEM!
        this.myPanel.AddAt(index, myControl);
    }
MaintainScrollPositionOnPostback = true