Как я могу динамически очистить все элементы управления в пользовательском элементе управления? - PullRequest
6 голосов
/ 19 мая 2010

Можно ли динамически (и вообще) очищать состояние всех дочерних элементов управления пользовательского элемента управления? (например, все его TextBoxes, DropDrownLists, RadioButton, DataGrids, Repeaters и т. д. - в основном все, что имеет ViewState)

Я стараюсь не делать что-то вроде этого:

foreach (Control c in myUserControl.Controls)
{
    if (c is TextBox)
    {
        TextBox tb = (TextBox)c;
        tb.Text = "";
    }
    else if (c is DropDownList)
    {
        DropDownList ddl = (DropDownList)c;
        ddl.SelectedIndex = -1;
    }
    else if (c is DataGrid)
    {
        DataGrid dg = (DataGrid)c;
        dg.Controls.Clear();
    }

    // etc.

}

Я ищу что-то вроде этого:

foreach (Control c in myUserControl.Controls)
    c.Clear();

... но, очевидно, этого не существует. Есть ли простой способ сделать это динамически / обобщенно?

Ответы [ 7 ]

3 голосов
/ 21 мая 2010

Я собирался предложить решение, аналогичное Задаче, за исключением того, что (как указано в sixlettervariables) нам необходимо реализовать его как метод расширения 1 и существенно включить точный тип передаваемого элемента управления (т.е. скопировать логику, которую вы опубликовали в ваш вопрос).

public static class ControlExtensions
{
    public static void Clear( this Control c )
    {
        if(c == null) {
            throw new ArgumentNullException("c");
        }
        if (c is TextBox)
        {
            TextBox tb = (TextBox)c;
            tb.Text = "";
        }
        else if (c is DropDownList)
        {
            DropDownList ddl = (DropDownList)c;
            ddl.SelectedIndex = -1;
        }
        else if (c is DataGrid)
        {
            DataGrid dg = (DataGrid)c;
            dg.Controls.Clear();
        }
        // etc....
    }
}

Это не очень элегантный метод, но ваш код на странице / контроле теперь более лаконичен

foreach (Control c in myUserControl.Controls) {
    c.Clear();
}

и теперь вы, конечно же, можете позвонить control.Clear() куда-нибудь еще в вашем коде.

2 голосов
/ 19 мая 2010

Вы можете сделать

foreach (Control c in myUserControl.Controls) {
    myUserControl.Controls.Remove(c);
}

Поскольку Controls - это просто список, вы можете вызвать Remove () для него, передав ему то, что вы хотите удалить.

РЕДАКТИРОВАТЬ: О, извините, я не прочитал это правильно. Я не знаю, как это сделать, может быть, кто-то здесь, кто хорошо разбирается в Reflection, может сделать это там, где вы могли бы сделать, как

foreach (Control c in myUserControl.Controls) {
    c = new c.Type.GetConstructor().Invoke();
}

или что-то, чтобы превратить его в свежеприготовленный компонент.

1 голос
/ 28 мая 2010

А как насчет метода Control.ClearChildViewState ?

MSDN состояния

Удаляет информацию о состоянии просмотра для всех дочерних элементов управления серверного элемента управления.

Я никогда этим не пользовался. Поэтому я не уверен, поможет ли это вам. Звучит хорошо, хотя, я думаю:)

1 голос
/ 19 мая 2010

Установка EnableViewState="false" на отдельных элементах управления может спасти вас, если в этом случае это не вызовет других проблем.

1 голос
/ 19 мая 2010
myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c));

Однако будьте осторожны, потому что вы изменяете список итерации. Это может привести к странному поведению.

1 голос
/ 19 мая 2010

Я не проверял это, но очистка viewstate для usercontrol может работать. Вы также можете предоставить пользовательский метод для пользовательского элемента управления:

UserControl:

public void Clear()
{
    this.ViewState.Clear();
}

страница:

myUserControlInstance.Clear();

Теперь снова я не проверял. Возможно, это только очистит StateBag для контейнера UserControl, а не его вложенных / дочерних элементов управления. Если вышеприведенное не сработает, вы можете попробовать использовать рекурсию, чтобы пройтись по дереву элементов управления для очистки представления состояния для всех дочерних элементов: 1010 *

UserControl:

public void Clear()
{
    ClearViewState(this.Controls);
}

private void ClearViewState(ControlCollection cc)
{
    foreach(Control c in cc)
    {
        if(c.HasControls())
        {
            //clear the child controls first
            ClearViewState(c.Controls);
        }        

        //then clear the control itself
        c.ViewState.Clear();
    }
}

страница:

myUserControlInstance.Clear();

Просто идея. Я не проверял это, но я думаю, что теоретически это могло бы работать. Одним из следствий этого будет вызов Clear в правильной точке жизненного цикла страницы / элементов управления, иначе это может не сработать.

Надеюсь, это поможет!

0 голосов
/ 19 мая 2010

Почему бы не сделать, как вы предлагаете:

foreach (Control c in myUserControl.Controls)
    c.Clear();

А затем реализовать Clear:

public static class UserController
{
    public static void Clear( this Control c )
    {
        c.Controls.Clear();
    }

    public static void Clear( this TextBox c )
    {
        c.Text = String.Empty;
    }
}

Это должно сделать это.

...