Действительно ли возможно динамично (и в общем) очищают состояние всех дочерних элементов управления пользовательского элемента управления? (например, все его TextBoxes, DropDrownLists, RadioButtons, DataGrids, Повторители, и т.д. - в основном что-либо, что имеет 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();
... но очевидно который не существует. Там какой-либо простой способ состоит в том, чтобы выполнить это динамично/в общем?
Я собирался предложить решение, похожее на решение Task, но (как указывает 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()
в любом другом месте вашего кода.
Вы можете сделать
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();
}
или что-то в этом роде, превратить его в недавно созданный компонент.
Я не тестировал это, но очистка состояния просмотра для пользовательского элемента управления может работать. Вы также можете предоставить собственный метод для пользовательского элемента управления:
usercontrol:
public void Clear()
{
this.ViewState.Clear();
}
page:
myUserControlInstance.Clear();
Опять же, я не тестировал. Возможно, это очистит только StateBag
для контейнера UserControl, а не его вложенные / дочерние элементы управления. Если вышеуказанное не работает, вы можете попробовать использовать рекурсию, чтобы пройти вниз по дереву элементов управления, чтобы очистить состояние просмотра для все дети:
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();
}
}
page:
myUserControlInstance.Clear();
Просто идея. Я не тестировал, но думаю, что теоретически это может сработать. Одним из последствий может быть вызов Clear в правильном месте жизненного цикла страницы / элементов управления, иначе это может не сработать.
Надеюсь, это поможет!
Настройка EnableViewState = "false"
для отдельных элементов управления может сэкономить вам работу, если в данном случае это не вызовет у вас других проблем.
Почему бы не сделать так, как вы предлагаете:
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;
}
}
Это должно сработать.
myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c));
Однако будьте осторожны, поскольку вы изменяете итерирующий список. Это может привести к странному поведению.
А как насчет метода Control.ClearChildViewState?
MSDN states
Удаляет информацию о состоянии представления для всех дочерних элементов управления сервера.
Однако я никогда не использовал этот метод. Поэтому я не уверен, поможет ли он вам. Хотя звучит неплохо, я думаю :)