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

Posted

技术标签:

【中文标题】如何动态清除用户控件中的所有控件?【英文标题】:How can I dynamically clear all controls in a user control? 【发布时间】:2011-02-21 12:48:03 【问题描述】:

是否可以动态(一般地)清除用户控件的所有子控件的状态? (例如,它的所有 TextBoxes、DropDrownLists、RadioButtons、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();

...但显然不存在。有没有简单的方法来动态/通用地完成这个?

【问题讨论】:

也许,您只需要一个简单的重定向? 【参考方案1】:

我打算提出一个类似于 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()

【讨论】:

我接受了这个答案,因为我认为这与我的初衷很接近。不幸的是,似乎没有完全动态的方式来清除所有子控件。【参考方案2】:

你可以的

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

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

编辑:哦,对不起,我没有正确阅读。我不知道有什么方法可以做到这一点,也许这里有一个擅长反射的人可以做到你可以做到的地方

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

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

【讨论】:

我认为迈克尔希望清除每个控件中的值/状态。不是集合中的控件本身。 KP:正确。我不想删除控件,只是清除它们(例如,清除 TextBox 文本值、清除 DropDownList 中的选定项、清除 DataGrid/Repeater 的内容等)。 Nilbert:没有问题,无论如何感谢您的意见。我喜欢你用反射概念去的地方;这就是我想知道的类型。【参考方案3】:

我还没有测试过,但是清除用户控件的视图状态可能会起作用。您也可以在用户控件上公开自定义方法:

用户控制:

public void Clear()

    this.ViewState.Clear();

页面:

myUserControlInstance.Clear();

现在我还没有测试。这可能只会清除 UserControl 容器的 StateBag,而不是其嵌套/子控件。如果上述方法不起作用,您可以尝试使用递归遍历控件树以清除所有子控件的视图状态:

用户控制:

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,否则它可能不起作用。

希望这会有所帮助!

【讨论】:

嗯..我自己测试过,似乎没有用..我会再玩一会儿,因为我喜欢这个概念.. 我开枪了。 ViewState 不是公共属性,因此您不能只清除它以进行控制。我喜欢在另一个答案中讨论的递归想法......我会留下这个答案,即使它不会工作,以防其他人有同样的想法......【参考方案4】:
myUserControl.Controls.ToList().ForEach(c => myUserControl.Controls.Remove(c));

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

【讨论】:

减 1,因为删除控件与原始问题无关。【参考方案5】:

在单个控件上设置 EnableViewState="false" 可能会节省您的工作,如果在这种情况下不会给您带来其他问题。

【讨论】:

【参考方案6】:

Control.ClearChildViewState 方法呢?

MSDN 状态

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

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

【讨论】:

听上去应该是完美的解决方案,可惜行不通。【参考方案7】:

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

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;
    

应该可以的。

【讨论】:

所以在foreach中每次调用Clear()都会调用静态Control.Clear()?因此,要使其正常工作,您将回到 Control.Clear() 中的“if (c is TextBox)...”?确实,那不是一个好的解决方案。 正确。 c 静态类型为 Control,因此扩展方法将查找 Control

以上是关于如何动态清除用户控件中的所有控件?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ViewModel 一次清除 WPF 中的所有控件?

动态创建DTPicker控件

如何在循环中动态更改用户控件的属性

清除 WebBrowser 附加控件内容以在用户窗体中重用它

用户控件,动态创建添加用户控件

WinForm用户控件动态创建添加控件timer控件--12月12日