logo
03

Поведение в режиме дизайна

Не полагайтесь на порядок установки значений свойств контрола дизайнером и тем более не подразумевайте, что некоторое свойство будет уже выставлено к моменту выставления другого свойства. Если избежать этого невозможно в силу особых свойств контрола, используйте интерфейс ISupportInitialize. Если некоторый компонент реализует этот интерфейс, дизайнер вставит вызов BeginInit перед началом инициализации и EndInit по окончании. Таким образом, вы сможете отследить, что инициализация закончена и, например, вызвать Recalculate для расчёта необходимых данных.

Во многих случаях необходимо знать, используется ваш контрол в данный момент в нормальных условиях (в работающем приложении) или же в режиме дизайна. Для этого необходимо использовать свойство DesignMode у сайта контрола (объекта, реализующего ISite). Если контрол уже сконструирован и находится в своём контейнере (например, форме), то его сайт можно получить, используя свойство Site – оно есть у любого компонента и контрола.

Если же вам необходимо узнать это еще в конструкторе, то всё становится несколько сложнее. Для начала попробуйте перепроектировать контрол таким образом, чтобы определение режима не требовалось в конструкторе или методе, вызываемом из него.

Если это невозможно по каким-либо причинам, придётся использовать медленный способ трассировки стека вызовов. В данном примере реализации такой проверки мы сначала пытаемся использовать быстрый способ. Если это не удалось, то мы просматриваем стек вызовов в поисках объекта, реализующего IDesignerHost. При нахождении такового мы делаем вывод, что мы находимся в дизайн-тайме. В реальном приложении может иметь смысл ограничить глубину просмотра стека.

private bool IsDesignMode()

{

if(Site != null )

return Site.DesignMode;

StackTrace stackTrace = new StackTrace();

int frameCount = stackTrace.FrameCount - 1;

for( int frame = 0; frame < frameCount; frame++ )

{

Type type = stackTrace.GetFrame(frame).GetMethod().DeclaringType;

if (typeof(IDesignerHost).IsAssignableFrom(type))

return true;

}

return false;

}

Также можно проверить, что исполняемой design-средой является Visual Studio: if (Application.ExecutablePath.ToLower().IndexOf("devenv.exe") > -1). Этот способ, хотя и быстрее, не позволит вам правильно определить другие возможные дизайнеры, например SharpDevelop.