如何动态清除用户控件中的所有控件?

时间:2022-02-03 15:48:30

Is it possible to dynamically (and generically) clear the state of all of a user control's child controls? (e.g., all of its TextBoxes, DropDrownLists, RadioButtons, DataGrids, Repeaters, etc -- basically anything that has ViewState)

是否可以动态(和一般)清除所有用户控件的子控件的状态? (例如,它的所有TextBox,DropDrownLists,RadioButtons,DataGrids,Repeater等 - 基本上任何有ViewState的东西)

I'm trying to avoid doing something like this:

我试图避免做这样的事情:

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.

}

I'm looking for something like this:

我正在寻找这样的东西:

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

...but obviously that doesn't exist. Is there any easy way to accomplish this dynamically/generically?

......但显然不存在。有没有简单的方法可以动态/通用地完成此操作?

7 个解决方案

#1


3  

I was going to suggest a solution similar to Task's except (as sixlettervariables points out) we need to implement it as 1 extension method and essentailly switch on the precise type of the control passed in (i.e. copy your logic that you posted in your question).

我打算建议一个类似于Task的解决方案,除了(因为六个变量指出)我们需要将它实现为1个扩展方法,并且essentailly打开传入的控件的精确类型(即复制你在问题中发布的逻辑) 。

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

It is not particularly elegent looking method but your code in your page/control is now the more succinct

它不是特别优雅的方法,但您的页面/控件中的代码现在更简洁

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

and you can of course now call control.Clear() anywhere else in you code.

当然,您现在可以在代码中的任何其他位置调用control.Clear()。

#2


2  

You can do

你可以做

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

Because Controls is just a list, you can call Remove() on it, passing it what you want to remove.

因为Controls只是一个列表,你可以在它上面调用Remove(),并将它传递给你想要删除的内容。

EDIT: Oh I'm sorry, I didn't read it correctly. I don't know of a way to do this, maybe someone here who is good with Reflection could make it where you could do like

编辑:哦,对不起,我没有正确阅读。我不知道如何做到这一点,也许这里有一个善于反思的人可以把它带到你可以做的地方

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

or something, to turn it into a freshly made component.

什么的,把它变成一个新制造的组件。

#3


1  

I haven't tested it, but clearing viewstate for the usercontrol may work. You could expose a custom method on the user control as well:

我还没有测试过,但清除用户控件的viewstate可能会有效。您也可以在用户控件上公开自定义方法:

usercontrol:

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

page:

myUserControlInstance.Clear();

Now again I haven't tested. It's possible this will only clear the StateBag for the UserControl container, and not its nested/child controls.. if the above doesn't work you could try using recursion to walk down the control tree to clear viewstate for all children:

现在我还没有测试过。这可能只会清除UserControl容器的StateBag,而不是它的嵌套/子控件..如果上面的方法不起作用,你可以尝试使用递归来走下控制树来清除所有子节点的视图状态:

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();

Just an idea. I haven't tested it but I think in theory it could work. One implication would be to call Clear at the correct point in the page/controls lifecycle, otherwise it may not work.

只是一个想法。我没有测试过,但我认为理论上它可以工作。一个含义是在页面/控件生命周期中的正确位置调用Clear,否则它可能无效。

Hope this helps!

希望这可以帮助!

#4


1  

myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c));

However, be careful, because you modify the iterating list. This could lead to some strange behaviour.

但是,要小心,因为您修改了迭代列表。这可能会导致一些奇怪的行为。

#5


1  

Setting EnableViewState="false" on the individual controls might save you the work, if it doesn't cause other problems for you in this instance.

如果在此实例中不会导致其他问题,则在各个控件上设置EnableViewState =“false”可能会为您节省工作。

#6


1  

What about the Control.ClearChildViewState method?

Control.ClearChildViewState方法怎么样?

MSDN states

Deletes the view-state information for all the server control's child controls.

删除所有服务器控件的子控件的视图状态信息。

I have never used this though. So I am unsure if it will help you. Sounds good though, I think :)

我从来没有用过这个。所以我不确定它是否会对你有所帮助。听起来不错,我认为:)

#7


0  

Why not do as you suggest:

为什么不按照你的建议去做:

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

And then implement 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;
    }
}

That should do it.

应该这样做。

#1


3  

I was going to suggest a solution similar to Task's except (as sixlettervariables points out) we need to implement it as 1 extension method and essentailly switch on the precise type of the control passed in (i.e. copy your logic that you posted in your question).

我打算建议一个类似于Task的解决方案,除了(因为六个变量指出)我们需要将它实现为1个扩展方法,并且essentailly打开传入的控件的精确类型(即复制你在问题中发布的逻辑) 。

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

It is not particularly elegent looking method but your code in your page/control is now the more succinct

它不是特别优雅的方法,但您的页面/控件中的代码现在更简洁

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

and you can of course now call control.Clear() anywhere else in you code.

当然,您现在可以在代码中的任何其他位置调用control.Clear()。

#2


2  

You can do

你可以做

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

Because Controls is just a list, you can call Remove() on it, passing it what you want to remove.

因为Controls只是一个列表,你可以在它上面调用Remove(),并将它传递给你想要删除的内容。

EDIT: Oh I'm sorry, I didn't read it correctly. I don't know of a way to do this, maybe someone here who is good with Reflection could make it where you could do like

编辑:哦,对不起,我没有正确阅读。我不知道如何做到这一点,也许这里有一个善于反思的人可以把它带到你可以做的地方

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

or something, to turn it into a freshly made component.

什么的,把它变成一个新制造的组件。

#3


1  

I haven't tested it, but clearing viewstate for the usercontrol may work. You could expose a custom method on the user control as well:

我还没有测试过,但清除用户控件的viewstate可能会有效。您也可以在用户控件上公开自定义方法:

usercontrol:

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

page:

myUserControlInstance.Clear();

Now again I haven't tested. It's possible this will only clear the StateBag for the UserControl container, and not its nested/child controls.. if the above doesn't work you could try using recursion to walk down the control tree to clear viewstate for all children:

现在我还没有测试过。这可能只会清除UserControl容器的StateBag,而不是它的嵌套/子控件..如果上面的方法不起作用,你可以尝试使用递归来走下控制树来清除所有子节点的视图状态:

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();

Just an idea. I haven't tested it but I think in theory it could work. One implication would be to call Clear at the correct point in the page/controls lifecycle, otherwise it may not work.

只是一个想法。我没有测试过,但我认为理论上它可以工作。一个含义是在页面/控件生命周期中的正确位置调用Clear,否则它可能无效。

Hope this helps!

希望这可以帮助!

#4


1  

myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c));

However, be careful, because you modify the iterating list. This could lead to some strange behaviour.

但是,要小心,因为您修改了迭代列表。这可能会导致一些奇怪的行为。

#5


1  

Setting EnableViewState="false" on the individual controls might save you the work, if it doesn't cause other problems for you in this instance.

如果在此实例中不会导致其他问题,则在各个控件上设置EnableViewState =“false”可能会为您节省工作。

#6


1  

What about the Control.ClearChildViewState method?

Control.ClearChildViewState方法怎么样?

MSDN states

Deletes the view-state information for all the server control's child controls.

删除所有服务器控件的子控件的视图状态信息。

I have never used this though. So I am unsure if it will help you. Sounds good though, I think :)

我从来没有用过这个。所以我不确定它是否会对你有所帮助。听起来不错,我认为:)

#7


0  

Why not do as you suggest:

为什么不按照你的建议去做:

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

And then implement 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;
    }
}

That should do it.

应该这样做。