nor*_*ndo 16 .net c# windows winforms
在C#中是否有办法检查对象是否挂起?我有一个TreeView,我需要知道它是否仍然挂起.
myTreeView.BeginUpdate();
myTreeView.SuspendLayout();
// Do Stuff.
myTreeView.EndUpdate();
myTreeView.ResumeLayout();
Run Code Online (Sandbox Code Playgroud)
因为我在递归函数中有这个代码,我想知道TreeView是否已被挂起.
Shu*_*oUk 11
根据verminity的回答你有一个选择:
使用以下课程
public class SuspendAwareTreeView : TreeView
{
public readonly T RealControl;
private int suspendCount;
public bool IsSuspended
{
get { return suspendCount > 0; }
}
public Suspendable(T real) { this.RealControl = real; }
public void SuspendLayout()
{
this.suspendCount++;
this.RealControl.SuspendLayout();
}
public void ResumeLayout()
{
this.RealControl.ResumeLayout();
this.suspendCount--;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在需要暂停它的内部使用此类.
显然,如果您将类传递给只需要控件或者控制之外的其他东西设置它,那么这将不起作用.
如果是这种情况,您将被迫使用各种不太令人满意的解决方案:
为了您的需求,当且仅当你控制这个完全运行在运行时版本(即控制企业环境中)以下的邪恶而有效的手段是适当的.只要您在升级时进行测试,就可以轻松地继续工作.
public class ControlInvader
{
private static readonly System.Reflection.FieldInfo layoutSuspendCount =
typeof(Control).GetField("layoutSuspendCount",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic);
private readonly Control control;
public bool IsSuspended
{
get
{
return 0 != (byte)layoutSuspendCount.GetValue(this.control);
}
}
public Suspendable(Control control) { this.control = control; }
}
Run Code Online (Sandbox Code Playgroud)
将其附加到TreeView,然后您可以随时检查值.
重申这一点很脆弱,并且完全不适用于底层运行时版本未受到严格控制的环境,以及您可以在可能的重大工作中解决这一问题.你最好包括一个静态初始化程序,它检查字段是否确实存在并且是正确的类型,如果没有则中止.
好吧,这是一种迟到的答案,但在内部,控件正在跟踪计数,并且只会在大多数简历声明中恢复.那你为什么一开始就关心它,你只需要确保你调用暂停并在finally块中恢复它:
void Recursive(Control c)
{
c.SuspendLayout();
try
{
if (existCondition) return;
// do stuff
Recursive(c);
}
finally
{
c.ResumeLayout(true);
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为以下是控制内部如何按以下顺序对您的通话作出反应:
c.SuspendLayout() // 1st call suspends layout
c.SuspendLayout() // 2nd and subsequent call only increase the count and does nothing.
....
c.ResumeLayout(true) // this decrease the count to 1 and does NOT actually resumes layout.
c.ResumeLayout(true) // this set the count to 0 and REALLY resumes layout.
Run Code Online (Sandbox Code Playgroud)
HTH
在Reflector中快速查看System.Windows.Forms.Control 中的 SuspendLayout 方法显示以下内容:
public void SuspendLayout()
{
this.layoutSuspendCount = (byte) (this.layoutSuspendCount + 1);
if (this.layoutSuspendCount == 1)
{
this.OnLayoutSuspended();
}
}
Run Code Online (Sandbox Code Playgroud)
由于它没有设置任何公共标志,并且 OnLayoutSuspended() 方法是内部的,因此似乎无法确定控件何时挂起。
您可以使用新的 Suspend 和 ResumeLayout 方法创建树视图的子类,但很难保证在所有情况下都会调用它们,因为基本方法不是虚拟的。