【问题标题】:Programmatically add UserControl with events以编程方式添加带有事件的 UserControl
【发布时间】:2009-12-14 14:33:39
【问题描述】:

我需要在面板中添加多个用户控件,以便进一步编辑包含的数据。我的用户控件包含一些面板、下拉列表和输入元素,它们填充在用户控件的 Page_Load 事件中。

protected void Page_Load(object sender, EventArgs e)
{
  // populate comparer ddl from enum
  string[] enumNames = Enum.GetNames(typeof (SearchComparision));

  var al = new ArrayList();
  for (int i = 0; i < enumNames.Length; i++)
    al.Add(new {Value = i, Name = enumNames[i]});

  scOperatorSelection.DataValueField = "Value";
  scOperatorSelection.DataTextField = "Name";
  ...

要显示的数据作为字段添加到用户控件中,在 Page_Load 上定义。事件的签名如下:

public delegate void ControlStateChanged(object sender, SearchCriteriaEventArgs eventArgs);

public event ControlStateChanged ItemUpdated;
public event ControlStateChanged ItemRemoved;
public event ControlStateChanged ItemAdded;

用户控件上的更新按钮触发如下方法:

protected void UpdateCriteria(object sender, EventArgs e)
{
  var searchCritCtl = (SearchCriteria) sender;

  var scEArgs = new SearchCriteriaEventArgs
  {
    TargetCriteria = searchCritCtl.CurrentCriteria.CriteriaId,
    SearchComparision = ParseCurrentComparer(searchCritCtl.scOperatorSelection.SelectedValue),
    SearchField = searchCritCtl.scFieldSelection.SelectedValue,
    SearchValue = searchCritCtl.scFilterValue.Text,
    ClickTarget = SearchCriteriaClickTarget.Update
  };
  if (ItemUpdated != null)
    ItemUpdated(this, scEArgs);
}

渲染页面从存储后端获取数据对象并将其显示在其 Page_Load 事件中。这是开始变得棘手的地方:我连接到自定义事件!

int idIt = 0;
foreach (var item in _currentSearch.Items)
{
  SearchCriteria sc = (SearchCriteria)LoadControl("~/content/controls/SearchCriteria.ascx");
  sc.ID = "scDispCtl_" + idIt;
  sc.ControlMode = SearchCriteriaMode.Display;
  sc.CurrentCriteria = item;
  sc.ItemUpdated += CriteriaUpdated;
  sc.ItemRemoved += CriteriaRemoved;
  pnlDisplayCrit.Controls.Add(sc);
  idIt++;
}

当第一次渲染页面时,一切都很好,我得到了我的所有数据。当我触发更新事件时,用户控件事件被正确触发,但用户控件的所有字段和控件都是NULL。经过一番研究,我不得不得出结论,在控件初始化之前触发了事件......

有没有办法防止这种行为/以某种方式覆盖页面生命周期?我无法在页面的 Init 事件中初始化用户控件,因为我必须访问 Session-Store(未在 Page_Init 中初始化)。

欢迎任何建议...

编辑:

由于我们在存储后端保存所有标准信息(包括标准计数)并且该存储使用会话中的用户 ID,我们不能使用 Page_Init... 只是为了澄清

编辑 #2:

我设法克服了一些问题。由于我现在使用简单类型,因此我能够以声明方式绑定所有数据(使用带有简单 ItemTemplate 的中继器)。它绑定到控件,它们以正确的方式呈现。在 Postback 中,所有数据都被反弹到用户控件,数据在 OnDataBinding 和 OnLoad 事件中可用,一切正常。

但是一旦进入真实事件(绑定到用户控件的按钮控件),所有的字段值都不知何故丢失了……

有人知道,页面生命周期如何在数据绑定/加载之后继续处理请求?这个问题我快疯了……

【问题讨论】:

  • 是否可以在 init 方法中初始化控件,然后在页面加载时执行会话内容?
  • 不,遗憾的是它不是......我们将完整的标准集合存储在商店中,由 Key 和登录用户的用户 ID 标识......因此我需要来自的用户 ID会议。

标签: asp.net user-controls


【解决方案1】:

动态控制可能是一场噩梦。诀窍是确保在回发中重新绑定所有内容。

【讨论】:

    【解决方案2】:

    我想出了一个解决方案;)

    如果我在用户控件内的按钮上使用 OnCommand 事件,我可以传递一个 CommandArgument。现在我将集合标识符绑定到按钮的 CommandArgument 参数,这使我能够处理用户控件内的所有回发。

    <asp:Button ID="scUpdate"
         runat="server"
         Text="Update"
         OnCommand="HandleCommand"
         CommandName="update"
         CommandArgument='<%# CriteriaId %>' />
    

    此声明在整个回发过程中保留 CriteriaId(一个 Guid),并使我能够识别基础集合(在页面上管理)上的修改条目。下面的代码sn-p展示了订阅页面的事件是如何被触发的。

    scEArgs = new SearchCriteriaEventArgs
              {
                    TargetCriteria = new Guid(e.CommandArgument.ToString()),
                    SearchComparision = ParseCurrentComparer(),
                    SearchField = scFieldSelection.SelectedValue,
                    SearchValue = scFilterValue.Text,
                    ClickTarget = SearchCriteriaClickTarget.Update
              };
    
    if (ItemUpdated != null)
      ItemUpdated(this, scEArgs);
    

    也许这个答案对某人有帮助,所以我会发布它;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      • 2013-05-02
      相关资源
      最近更新 更多