Статьи

Сохранение изображения в качестве переходных данных


Если вы разрабатывали приложения для Windows Phone 7, вы, вероятно, знаете о надгробиях и информации, которая должна обрабатываться в ходе этого процесса.
Важным фактором является хранение данных, чтобы обеспечить бесперебойную работу и создать иллюзию того, что приложение всегда работало. Эти данные обычно известны как
переходные данныеи это, по сути, информация, которая не будет сохраняться вне жизненного цикла приложения. Полезным примером временных данных может быть пользователь, заполняющий форму и заполняющий различные текстовые поля. Затем приложение захороняется, и пользователь в конечном итоге возвращается в приложение, нажимая кнопку «назад». По умолчанию при перезагрузке приложения текстовые поля будут пустыми с момента создания нового экземпляра. Чтобы создать иллюзию запуска одного и того же экземпляра и улучшить взаимодействие с пользователем, приложение должно пополнить все данные, которые были введены до захоронения. Эти данные должны храниться в 
свойстве
PhoneApplicationPage.State .

Это свойство имеет ограничение 2 МБ на страницу и 4 МБ для всего приложения, поэтому лучше хранить элементы только при необходимости. Также важно помнить, что к этому свойству можно получить доступ только в методах OnNavigatedTo и OnNavigatedFrom . Чтобы узнать больше об использовании свойства State и хранении переходных данных, вы можете прочитать учебные пособия по жизненному циклу приложений, найденные в обучающем комплекте для Windows Phone 7 (обновление RTM), и ознакомиться с документацией MSDN «Как» . Следует отметить, что альтернативой переходным данным являются постоянные данные.и это информация, которая потребуется между жизненными циклами приложения, такие как пользовательские настройки, сохраненная информация об игре, данные приложения и т. д. Для разработки WP7 постоянные данные должны храниться в изолированном хранилище приложения или на удаленном сервере.

Эта проблема

В приложении, над которым я работаю, мне нужно сохранить изображение как временные данные. Видя, что свойство State принимает тип объекта в качестве значения, я попытался напрямую передать поток изображения, чтобы увидеть, что произойдет. Оказывается, когда base.OnNavigatedFrom (e) был вызван, три исключения были выданы :

A first chance exception of type 'System.Security.SecurityException' occurred in System.Runtime.Serialization.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'System.Security.SecurityException' occurred in System.Runtime.Serialization.dll

В режиме выпуска это привело к повреждению стека навигации и, следовательно, пользователю не удалось нажать кнопку «назад», чтобы вернуться в приложение после того, как оно было захоронено. Более подробно, казалось, что Visual Studio поймает это в обработчике события Application_UnhandledException . Трассировка стека, предоставленная объектом исключения, была:

at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)
at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serial

При удалении потока изображения это исключение никогда не создавалось, поэтому кажется, что существует проблема сериализации при непосредственном предоставлении потока.

Решение

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

//_imageStream is a variable that stores the stream (e.g. this might be obtained
//from the PhotoChooserTask's completed event parameter 'e.ChosenPhoto')
if (_imageStream != null)
{
//reset the stream position so it's at the beginning.
//this is important because any previous readings of the stream will ...
//position it at the end, causing an error when reading it.
 _imageStream.Position = 0;
      //Create a memorystream which is used to write to a byte array
     MemoryStream ms = new MemoryStream();
      //Create a byte array of the same length as the image stream
      byte[] buffer = new byte[_imageStream.Length];
      //read the imagestream into the byte array
      int read;
      while ((read = _imageStream.Read(buffer, 0, buffer.Length)) > 0)
      {
            ms.Write(buffer, 0, read);
      }
      //Save the image to the page's 'State' property
      if (State.ContainsKey("MyImage")) State.Remove("MyImage");
State.Add("MyImage", image);
}
Приведенный выше код преобразует ваш поток в массив байтов и сохранит массив в состояние страницы. Это необходимо сделать в методе OnNavigatedFrom, поскольку свойство State доступно только отсюда и OnNavigatedTo .

Последний шаг в методе OnNavigatedTo — преобразовать массив байтов обратно в поток и назначить его элементу управления изображением.

if(State.ContainsKey("MyImage"))
{
//instantiate a new image and set it as the the previously stored stream
BitmapImage bmpImage = new BitmapImage();
//set the source of the BitmapImage to be the stream we saved earlier
bmpImage.SetSource(new MemoryStream(State["MyImage"] as Byte[]));
//update the image control to show the saved image
myImageControl.Source = bmpImage;
}

Это должно теперь отображать изображение, когда приложение перезапускается после того, как он был захоронен. Вы должны добавить больше кода для проверки ошибок, чтобы сделать его более устойчивым (например, убедитесь, что «MyImage» на самом деле является байтовым массивом), но, надеюсь, приведенный выше код поможет вам начать работу. Если у вас есть какие-либо комментарии или вопросы, не стесняйтесь размещать сообщения ниже.

Надеюсь это поможет!