Подтвердить что ты не робот

Лучший способ найти элемент управления в ASP.NET

У меня есть сложная форма asp.net, имеющая хотя бы 50-60 полей в одной форме, например Multiview, внутри MultiView у меня есть GridView, а внутри GridView у меня есть несколько CheckBoxes.

В настоящее время я использую цепочку метода FindControl() и получаю дочерний идентификатор.

Теперь, мой вопрос: есть ли другой способ/решение найти вложенный элемент управления в ASP.NET.

4b9b3361

Ответ 1

Если вы ищете определенный тип управления, вы можете использовать рекурсивный цикл, подобный этому, http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol-recursive-with-generics.aspx

Вот пример, который я сделал, который возвращает все элементы управления данного типа

/// <summary>
/// Finds all controls of type T stores them in FoundControls
/// </summary>
/// <typeparam name="T"></typeparam>
private class ControlFinder<T> where T : Control 
{
    private readonly List<T> _foundControls = new List<T>();
    public IEnumerable<T> FoundControls
    {
        get { return _foundControls; }
    }    

    public void FindChildControlsRecursive(Control control)
    {
        foreach (Control childControl in control.Controls)
        {
            if (childControl.GetType() == typeof(T))
            {
                _foundControls.Add((T)childControl);
            }
            else
            {
                FindChildControlsRecursive(childControl);
            }
        }
    }
}

Ответ 2

это может помочь.

public static class ControlExtensions
{
    /// <summary>
    /// recursively finds a child control of the specified parent.
    /// </summary>
    /// <param name="control"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public static Control FindControlRecursive(this Control control, string id)
    {
        if (control == null) return null;
         //try to find the control at the current level
        Control ctrl = control.FindControl(id);

        if (ctrl == null)
        {
            //search the children
            foreach (Control child in control.Controls)
            {
                ctrl = FindControlRecursive(child, id);

                if (ctrl != null) break;
            }
        }
        return ctrl;
    }
}

    public void Page_Load(object sender, EventArgs e)
    {
        //call the recursive FindControl method
        Control ctrl = this.FindControlRecursive("my_control_id");
    }

Ответ 3

Поздно, как обычно. Если кто-то еще заинтересован в этом, существует ряд связанных SO вопросов и ответов. Моя версия метода рекурсивного расширения для решения этой проблемы:

public static IEnumerable<T> FindControlsOfType<T>(this Control parent)
                                                        where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is T)
        {
            yield return (T)child;
        }
        else if (child.Controls.Count > 0)
        {
            foreach (T grandChild in child.FindControlsOfType<T>())
            {
                yield return grandChild;
            }
        }
    }
}

Ответ 4

Все выделенные решения используют рекурсию (которая является дорогостоящей). Вот более чистый путь без рекурсии:

public T GetControlByType<T>(Control root, Func<T, bool> predicate = null) where T : Control 
{
    if (root == null) {
        throw new ArgumentNullException("root");
    }

    var stack = new Stack<Control>(new Control[] { root });

    while (stack.Count > 0) {
        var control = stack.Pop();
        T match = control as T;

        if (match != null && (predicate == null || predicate(match))) {
            return match;
        }

        foreach (Control childControl in control.Controls) {
           stack.Push(childControl);
        }
    }

    return default(T);
}

Ответ 5

FindControl не выполняет поиск внутри вложенных элементов управления рекурсивно. Он находит только элементы управления, которые NamigContainer - это элемент управления, который вы вызываете FindControl.

Это причина, по которой ASP.Net не рекурсивно просматривает ваши вложенные элементы управления:

  • Производительность
  • Предотвращение ошибок
  • Повторное использование

Считайте, что вы хотите инкапсулировать свои GridViews, Formviews, UserControls и т.д. внутри других UserControl для повторного использования. Если бы вы выполнили всю логику на своей странице и получили доступ к этим элементам управления с помощью рекурсивных циклов, это будет очень сложно реорганизовать. Если вы внедрили свою логику и методы доступа с помощью обработчиков событий (f.e. RowDataBound of GridView), это будет намного проще и менее подвержено ошибкам.

Ответ 6

Управление действиями при управлении

Создайте ниже класс в базовом классе. Класс Чтобы получить все элементы управления:

public static class ControlExtensions
{
    public static IEnumerable<T> GetAllControlsOfType<T>(this Control parent) where T : Control
    {
        var result = new List<T>();
        foreach (Control control in parent.Controls)
        {
            if (control is T)
            {
                result.Add((T)control);
            }
            if (control.HasControls())
            {
                result.AddRange(control.GetAllControlsOfType<T>());
            }
        }
        return result;
    }
}

Из базы данных: Получите идентификаторы всех действий (например, divAction1, divAction2....) в DATASET (DTActions) для конкретного пользователя.

В Aspx: в HTML Поместите действие (кнопка, якорь и т.д.) в div или span и дайте им идентификатор, например

<div id="divAction1" visible="false" runat="server" clientidmode="Static">   
                <a id="anchorAction" runat="server">Submit
                        </a>                      
                 </div>

IN CS: Используйте эту функцию на своей странице:

private void ShowHideActions()
    {

        var controls = Page.GetAllControlsOfType<HtmlGenericControl>();

        foreach (DataRow dr in DTActions.Rows)
        {          

            foreach (Control cont in controls)
            {

                if (cont.ClientID == "divAction" + dr["ActionID"].ToString())
                {
                    cont.Visible = true;
                }

            }
        }
    }

Ответ 7

Рекурсивно найти все элементы управления, соответствующие указанному предикату (не включая root Control):

    public static IEnumerable<Control> FindControlsRecursive(this Control control, Func<Control, bool> predicate)
    {
        var results = new List<Control>();

        foreach (Control child in control.Controls)
        {
            if (predicate(child))
            {
                results.Add(child);
            }
            results.AddRange(child.FindControlsRecursive(predicate));
        }

        return results;
    }

Использование:

myControl.FindControlsRecursive(c => c.ID == "findThisID");

Ответ 8

Я решил просто создать словари управления. Сложнее поддерживать, может работать быстрее, чем рекурсивный FindControl().

protected void Page_Load(object sender, EventArgs e)
{
  this.BuildControlDics();
}

private void BuildControlDics()
{
  _Divs = new Dictionary<MyEnum, HtmlContainerControl>();
  _Divs.Add(MyEnum.One, this.divOne);
  _Divs.Add(MyEnum.Two, this.divTwo);
  _Divs.Add(MyEnum.Three, this.divThree);

}

И перед тем, как я получу большие пальцы, чтобы не отвечать на вопрос OP...

Q: Теперь, на мой вопрос, есть ли другой способ/решение найти вложенный элемент управления в ASP.NET? A: Да, не нужно искать их в первую очередь. Зачем искать вещи, которые вы уже знаете? Лучше создать систему, позволяющую ссылку известных объектов.

Ответ 9

В этой статье описывается, как найти управление рекурсивно по типу, но его реализация содержит один изъян, который приводит к потере "основанного" элемента управления

Ниже представлена ​​фиксированная версия:

        /// <summary>
        /// Find control (recursively) by type 
        /// (http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol-recursive-with-generics.aspx)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="controls"></param>
        /// <returns></returns>
        public static T FindControl<T>(System.Web.UI.ControlCollection controls) where T : class
        {
            T found = default(T);

            if (controls != null && controls.Count > 0)
            {
                for (int i = 0; i < controls.Count; i++)
                {
                    if (found != null) break;
                    if (controls[i] is T)
                    {
                        found = controls[i] as T;
                        break;
                    }
                    found = FindControl<T>(controls[i].Controls);
                }
            }

            return found;
        }

Ответ 10

В следующем примере определяется обработчик события Button1_Click. При вызове этот обработчик использует метод FindControl для поиска элемента управления с свойством ID TextBox2 на содержащейся странице. Если элемент управления найден, его родительский элемент определяется с использованием свойства Parent, а родительский идентификатор управления записывается на страницу. Если TextBox2 не найден, на страницу записывается "Control Not Found".

private void Button1_Click(object sender, EventArgs MyEventArgs)
{
      // Find control on page.
      Control myControl1 = FindControl("TextBox2");
      if(myControl1!=null)
      {
         // Get control parent.
         Control myControl2 = myControl1.Parent;
         Response.Write("Parent of the text box is : " + myControl2.ID);
      }
      else
      {
         Response.Write("Control not found");
      }
}