检查挂起布局

检查挂起布局

问题描述:

有没有在C#中检查对象是否挂起的方法?我有一个TreeView,我需要知道它是否仍然挂起。检查挂起布局

myTreeView.BeginUpdate(); 
myTreeView.SuspendLayout(); 

// Do Stuff. 

myTreeView.EndUpdate(); 
myTreeView.ResumeLayout(); 

因为我有这个代码递归函数我想知道如果TreeView已被暂停。

+1

目前尚不清楚你的意思是什么 “暂停”。 – 2009-04-22 14:38:20

+1

我会标记这个来表示你正在使用什么类库... WinForms或者WPF。 – 2009-04-22 15:13:08

从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--; 
    } 
} 

然后使用这个类的一切内部。

显然这不会工作,如果你曾经将类传递给仅仅期望控件或者其他控件以外的东西来设置它。

如果这是你将*去与各种不到愉快的解决方案的情况下:

  • 写一个新的用户控件包装了TreeView和推迟到它的所有呼叫,但保持暂停状态。
    • 生成的实例不再是“is-a TreeView”,这会导致问题。
    • 维护工作可能很高。
    • 如果由于某种原因树视图决定暂停自己,这将打破。
    • 新版本的运行时不太可能破坏任何东西,你根本无法不费力地获得新功能。
  • 实现一个全新的TreeViewEx暴露出这种状态
    • 产生的实例不再“是一个树视图”,这将导致问题。
    • 维护工作可能高
    • 也突破不了,因为你有完全的控制,可以从运行时不会破坏任何原有虽然
    • 新版本的分歧,你根本不会得到没有显著努力的新功能(可能违反法律/ EULA)。
  • 破坏封装
    • 没有改变FO类型系统,一切继续工作。
    • 维护工作运行时改变潜在的高
    • 应用将打破,如果他们下的运行时更改

对于您的需求当且仅当你控制这个完全运行在运行时版本(即受控企业环境)以下邪恶但有效的破解是合适的。只要你测试任何时候你升级它可能会继续努力工作。

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

将此附加到您的TreeView,然后您可以随时检查该值。

重申这是脆弱并且完全不适合的环境,其中底层运行时的版本没有严格控制,并且您可以在这里处理可能的重大努力以解决这个突变问题。 你会很好地包含一个静态初始化程序,该初始化程序检查该字段是否实际存在并且是正确的类型,如果不是,则会中止。

就让我们来看看在Reflector在从Control的SuspendLayout方法显示如下:

public void SuspendLayout() 
{ 
    this.layoutSuspendCount = (byte) (this.layoutSuspendCount + 1); 
    if (this.layoutSuspendCount == 1) 
    { 
     this.OnLayoutSuspended(); 
    } 
} 

因为它不设置任何公开的标志,和OnLayoutSuspended()方法是内部无论如何都不知道控制权何时被暂停。

您可以使用新的Suspend和ResumeLayout方法创建树视图的子类,但由于基本方法不是虚拟的,因此很难保证它们在所有情况下都会被调用。

+0

为什么你不能使用反射来获得layoutSuspendCount成员? – 2009-04-23 04:21:19

好吧,这是一种迟到的回答,但在内部,控制器正在跟踪计数,并且只会在最简历语句中恢复。那么,为什么你在第一时间关心它,你只要确保你叫暂停,并在finally块恢复它:

void Recursive(Control c) 
{ 
    c.SuspendLayout(); 
    try 
    { 
    if (existCondition) return; 
    // do stuff 
    Recursive(c); 
    } 
    finally 
    { 
    c.ResumeLayout(true); 
    } 
} 

这工作,因为下面是如何控制内部反应您的通话以下顺序:

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. 

HTH