如何动态清除用户控件中的所有控件?
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 中的所有控件?