将动态控件插入控件集合的中间 [英] Insert dynamic controls into middle of controls collection

查看:100
本文介绍了将动态控件插入控件集合的中间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

this is my very first post! I'm pretty desperate so I'm going above and beyond my standard googling. I believe this is an advanced or expert-level .NET question.

问题是我建立了一个.NET Web应用程序,该应用程序需要能够将用户控件动态地插入列表的中间.我对动态控件非常满意,只要它们只需要添加到列表的末尾即可(即:我熟悉这样的文章: http://msdn.microsoft.com/zh-cn/library/ms972976.aspx ).但是,如果我需要在Controls集合的前面或中间的某个位置添加UserControl,则由于丢掉了控件的UniqueID,我几乎迷失了.

The problem is that I have built a .NET web application that needs to be able to insert user controls dynamically into the middle of a list. I'm quite comfortable with dynamic controls so long they only need to be added to the end of the list (ie: I'm familiar with articles like this: http://msdn.microsoft.com/en-us/library/ms972976.aspx). However, if I need to add a UserControl to the front of a Controls collection or somewhere in the middle I'm pretty much lost since the UniqueID of the control is thrown off.

作为一个简化的示例,假设我有一个Panel,要向其中添加一个名为MyControl.ascx的UserControls列表.我还有一些事件可以在页面上触发,该事件需要将MyControl.ascx动态插入面板的Controls集合的指定索引中.我还需要订阅MyControl.ascx上的一个或多个事件.这意味着在这些控件上的事件将被触发或否则将不会触发之前,需要先加载控件.如果您不知道我指的是什么,那我要么措辞不佳,要么这个问题对您来说可能太困难了:)

As a simplified example, let's say that i have a Panel to which I am adding a list of UserControls called MyControl.ascx. I also have some event that can get fired on the page to that needs to dynamically insert a MyControl.ascx into the specified index of the Controls collection of the panel. I also have one or more events on MyControl.ascx to which I need to subscribe. This means that the controls need to be loaded BEFORE the events on these controls would fire or else they will not fire. If you don't know to what I'm referring then I either worded the question poorly or this question might be too difficult for you :)

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

Below is some C# pseudocode to demonstrate the issue. The problem is that the Controls.AddAt(index, control) method does NOT adjust the UniqueID values of the controls accordingly. For example, consider the following controls in a Controls collection:

无论我实际上是否在编写直接依赖于UniqueID的代码,.NET都间接使用UniqueID将先前回发中触发的事件链接在一起,并将控件加载到新的回发中.以我之前的示例为例:

Whether I'm actually writing code that directly depends on the UniqueID or not, .NET indirectly uses the UniqueID to link together the events that were fired on the previous postback with the controls get loaded on the new postback. Taking my previous example of:

在初始Page Load (Page.IsPostback == false)

<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>value1</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl01</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl02</td>
    <td>value3</td>
  </tr>
</table>

从其他某个控件回发(Page.IsPostback == false)后,该控件想要将该控件插入索引0:

After a postback (Page.IsPostback == false) from some other control that wants to insert the control at index 0:

如果我执行Controls.AddAt(0, newControl),则控件集合看起来像这样:

If i do a Controls.AddAt(0, newControl) then the Controls collection looks something like this:

<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl03</td>
    <td>value0  <== the controls' unique IDs do not shift!</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl00</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl01</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>ctl02</td>
    <td>value3</td>
  </tr>
</table>

因此,如果我单击具有Value == value0和UniqueID == ctl03的控件中的链接按钮,则这些控件的顺序将如下所示,并且在回发时,UniqueID将不符合我想要的顺序.这将导致click事件附加到错误的控件上:

So if i were to click on a linkbutton in the control with Value == value0 and UniqueID == ctl03, the controls would be ordered like the following on post-back and the UniqueIDs would not be in the order i want. This will cause the click event to attach to the wrong control:

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

如果我不必处理这些动态控件中的事件,则可能不会有问题.这是我的代码:

If i didn't have to handle events from these dynamic controls this probably wouldn't be a problem. Here is my code:

// 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);
    }

请帮助.这是杀了我.如果您需要更多信息或有疑问,请告诉我,我们很乐意提供更多信息.非常感谢您的帮助!

Please help. This one is killing me. If you need more information or have questions please let me know and I'd be happy to provide more info. I GREATLY appreciate your help!

推荐答案

要使自动编号生效,您希望将每个回发的控件以相同的顺序添加到面板中.显然,在回发时,必须为控件分配唯一的ID,否则您将不会获得控件事件.

To make automatic numbering work, you want the controls to be added to the panel in the same order for every postback. Obviously, on a postback, the controls have to have their unique IDs assigned, or you wouldn't get the control event.

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

UniqueID is initialised on first use to the value of the Control.ID* property. If that property is not set, it is automatically generated as ctlxx, as you have observed. Once assigned, a control's UniqueID is read-only.

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

Therefore, if you have some form of primary key, you can set the ID property of the control when you create it based on that primary key. The UniqueID will then be set to that value when the page loads its state.

  • 脚注:UniqueID属性实际上是命名容器的前缀和ID属性的组合.
  • Footnote: the UniqueID property is actually a combination of the naming container's prefix and the ID property.

这篇关于将动态控件插入控件集合的中间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆