Проверьте SuspendLayout

Все, что вы хотите сделать, это создать POJO , который содержит testValue и anotherValue и объявить класс вне вашего класса компонента, например:

class ExampleBean {
  private String testValue;
  private String anotherValue;

  //getters and setters
}

готово, вы можете сохранить ссылку этого класса в свой класс компонентов и получить доступ к значению, например:

public class ABC extends CDE implements EFG {
    ExampleBean exampleBean = new ExampleBEan();
    public void firstMethod(valueOne, valueTwo) {
        exampleBean.setValueOne(valueOne);
        exampleBean.setAnotherValue(valueTwo);
    }

    public void readMethod() {
        String value = exampleBean.getValueOne();
    }
}

16
задан norlando 22 April 2009 в 16:52
поделиться

3 ответа

Following on from verminity's answer you do have one option:

Use the following class

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

Then use this class for everything internally where you need to suspend it.

Obviously this won't work if you ever pass the class around to something that only expects a control or if something else outside your control sets it.

If this is the case you would be forced to go with a variety of less than pleasant solutions:

  • Write a new User control which wraps the TreeView and defers all calls to it but maintains the suspended state.
    • Результирующий экземпляр больше не является «Tree-TreeView», что вызовет проблемы.
    • Возможно, потребуется много усилий по обслуживанию.
    • Если по какой-то причине древовидная структура решила приостановить себя, это сломается.
    • Новая версия среды выполнения вряд ли что-то сломает, вы просто не получите новую функциональность без усилий.
  • Реализация совершенно нового TreeViewEx, который предоставляет это состояние
    • Результирующий экземпляр больше не является «Tree-TreeView», что вызовет проблемы.
    • усилия по обслуживанию, возможно, высокие
    • , никогда не могут сломаться, поскольку у вас есть полный контроль, могут отличаться от оригинала, хотя
    • новая версия среды выполнения вряд ли что-то сломает, вы просто не получите новую функциональность без значительных усилий (возможно, в нарушение закона / EULA).
  • Violate Encapsulation
    • No alteration fo the type system, everything else continues to work.
    • Maintenance effort potentially high on runtime change
    • apps will break if the runtime changes underneath them

For your needs if and only if you control the runtime versions this operates on entirely (i.e. a controlled corporate environment) the following evil but effective hack is appropriate. So long as you test any time you upgrade it may well keep working with little effort.

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

Attach this to your TreeView and then you can inspect the value whenever you like.

To reiterate this is fragile and entirely inappropriate for an environment where the version of the underlying runtime is not strictly controlled and where you can handle possible significant efforts to fix this on a breaking change. You would do well to include a static initializer which checks if the field actually existed and was the right type and aborted if not.

11
ответ дан 30 November 2019 в 21:54
поделиться

Быстрый просмотр в Reflector метода SuspendLayout из System.Windows.Forms.Control показывает следующее:

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

Поскольку он не устанавливает никаких открытых флагов, и метод OnLayoutSuspended () является внутренним, по-видимому, в любом случае не удается определить, когда элемент управления приостановлен.

Вы можете создать подкласс древовидного представления с помощью новых методов Suspend и ResumeLayout, но это будет трудно гарантировать. что они будут вызываться при любых обстоятельствах, поскольку базовые методы не являются виртуальными.

3
ответ дан 30 November 2019 в 21:54
поделиться

Что ж, это вроде как запоздалый ответ, но внутренне элемент управления отслеживает счетчик и возобновит работу только в самом последнем операторе возобновления. Так зачем вам это вообще нужно? Просто убедитесь, что вы вызываете приостановку и возобновляете ее в блоке finally:

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

Это работает, потому что ниже показано, как Control внутренне реагирует на ваш вызов в следующем порядке:

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

9
ответ дан 30 November 2019 в 21:54
поделиться