пятница, февраля 11, 2011

Проблемы с Silverlight приложением, открытым в фоне

Иногда вредные пользователи открывают окно с silverlight приложением в фоне.
В отдельной табке, например.

В этом случае некоторый наш код инициализации в контролах столкнется, к примеру, со значениями ActualWidth и ActualHeight = 0, отсутствием некоторых контролов в дереве и прочими косяками.

Возможно, есть красивый способ решить эту проблему, но я его пока не нашел.
Поэтому опишу свой.

Предположим, у нас есть контрол MyPanel, в котором есть метод void CalcSomething(), которому позарез нужно высчитать что-то хитрое основываясь на текущих размерах контрола.

1. Добавляем поле

private readonly ManualResetEvent layout_complete = new ManualResetEvent( false );

2. В конструкторе MyPanel подписываемся на SizeChanged:

SizeChanged += on_size_changed;

3. В обработчике события смотрим, посчитан ли уже размер для нашего контрола:

private void on_size_changed( object sender, SizeChangedEventArgs e )
{
if (ActualHeight != 0 && ActualWidth != 0)
_layout_complete.Set();
}

4. Если раньше наш метод CalcSomething вызывался просто, теперь он должен стартовать в отдельном потоке:

new Thread(CalcSomething).Start();

5. Исполнение CalcSomething отложим до момента, когда будет послан сигнал через _layout_complete:

private void CalcSomething()
{
_layout_complete.WaitOne()
...старый код работы с UI...

6. И стоит учитывать, что поскольку мы теперь находимся в отдельном потоке, работать с UI напрямую нельзя.

private void CalcSomething()
{
_layout_complete.WaitOne()
Deployment.Current.Dispatcher.BeginInvoke( () =>
{
...старый код работы с UI...
} );
}

Комментариев нет: