Windows Phone 8. C#. Lockscreen background from isolated storage. Exception - c#

I'm trying to implement a lockscreen background application on Windows Phone 8 using C#. The idea is that when a user clicks a button, PhotoChooserTask is initiated. When he picks a photo from his media library, it's copied to isolated storage and then set as a lockscreen background.
The problem is that Windows Phone requires a unique name for each new lockscreen picture, so the solution has to be the following:
The user selects a photo from the library
2.1 If the current lockscreen picture EndsWith("_A.jpg") the chosen photo is copied to the isolated storage as photobackground_B.jpg and is set as lockscreen background
2.2. Otherwise, if the current lockscreen picture doesn't meet the EndsWith("_A.jpg") condition, then the chosen photo is copied to the isolated storage as photobackground_A.jpg and is set as lockscreen background.
Thus, the A/B switching logic is implemented so that each new lockscreen background has a unique name.
However, my code does not work.In particular the following line throws an exception:
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_A.jpg", UriKind.Absolute));
What seems to be the problem?
P.S. I'm completely new to programming, so I would also greately appreciate an explanation and a proper code sample. Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;
using Day2Demo.Resources;
using System.Windows.Media;
using System.IO;
using System.IO.IsolatedStorage;
using Microsoft.Xna.Framework.Media;
namespace Day2Demo
{
public partial class MainPage : PhoneApplicationPage
{
PhotoChooserTask photoChooserTask;
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void button1_Click(object sender, RoutedEventArgs e)
{
//check if current app provided the lock screen image
if (!Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication)
{
//current image not set by current app ask permission
var permission = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
if (permission == Windows.Phone.System.UserProfile.LockScreenRequestResult.Denied)
{
//no permission granted so return without setting the lock screen image
return;
}
}
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
photoChooserTask.Show();
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var currentImage = Windows.Phone.System.UserProfile.LockScreen.GetImageUri();
if (currentImage.ToString().EndsWith("_A.jpg"))
{
var contents = new byte[1024];
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var local = new IsolatedStorageFileStream("photobackground_B.jpg", FileMode.Create, store))
{
int bytes;
while ((bytes = e.ChosenPhoto.Read(contents, 0, contents.Length)) > 0)
{
local.Write(contents, 0, bytes);
}
}
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_B.jpg", UriKind.Absolute));
}
}
else
{
var contents = new byte[1024];
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var local = new IsolatedStorageFileStream("photobackground_A.jpg", FileMode.Create, store))
{
int bytes;
while ((bytes = e.ChosenPhoto.Read(contents, 0, contents.Length)) > 0)
{
local.Write(contents, 0, bytes);
}
}
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_A.jpg", UriKind.Absolute));
}
}
}
}
}
}

Here are some suggestions for you:
You may be overcomplicating the matter of naming the file. First, I'd say if the app is the current lock screen manager, delete the existing lock screen image, then create a new image name using Guid.NewGuid. Guids are guaranteed to be unique upon generation so you'll never run into a naming collision here.
You're using antiquated storage APIs that may lock your UI and cause it to become non-responsive. There are new async file storage APIs provided in Windows Phone 8 and it might help to familiarize yourself with them in the future. The code sample provided will give you a start.
The URI you're ultimately going to provide is likely most easily generated by giving the OS a system-relative file path (i.e. C:\) and that's easily accessible from the StorageFile.Path Property.
Modify your event handler to something along the lines of the following code and see how you fare. You will need to add a using directive to import the System.IO namespace to use the OpenStreamForWriteAsync Extension:
private async void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
// Load the image source into a writeable bitmap
BitmapImage bi = new BitmapImage();
bi.SetSource(e.ChosenPhoto);
WriteableBitmap wb = new WriteableBitmap(bi);
// Buffer the photo content in memory (90% quality; adjust parameter as needed)
byte[] buffer = null;
using (var ms = new System.IO.MemoryStream())
{
int quality = 90;
e.ChosenPhoto.Seek(0, SeekOrigin.Begin);
// TODO: Crop or rotate here if needed
// Resize the photo by changing parameters to SaveJpeg() below if desired
wb.SaveJpeg(ms, wb.PixelWidth, wb.PixelHeight, 0, quality);
buffer = ms.ToArray();
}
// Save the image to isolated storage with new Win 8 APIs
var isoFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var nextImageName = Guid.NewGuid() + ".jpg";
var newImageFile = await isoFolder.CreateFileAsync(nextImageName, Windows.Storage.CreationCollisionOption.FailIfExists);
using (var wfs = await newImageFile.OpenStreamForWriteAsync())
{
wfs.Write(buffer, 0, buffer.Length);
}
// Use the path property of the StorageFile to set the lock screen URI
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri(newImageFile.Path, UriKind.Absolute));
}
}

Thanks lthibodeaux for the awesome idea) Everything worked except for the SetImageUri line.
This one seems to do the business: Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/" + nextImageName, UriKind.Absolute))
Thanks again!

Related

Telegram Bot C# - Send object Bitmap

I have to "generate" a png file and send it to the Telegram bot via SendPhotoAsync of SeendDocumentAsync.
This is a piece of my C# code:
...
Bitmap speedometer = new Bitmap(#"C:\Immagini\bot\speedometer.png");
Bitmap pointer = new Bitmap(#"C:\Immagini\bot\pointer.png");
Bitmap finalImage = new Bitmap(speedometer);
using (Graphics graphics = Graphics.FromImage(finalImage))
{
Bitmap rotatedPointer = RotateImage(pointer, efficienza_int * (float)1.8);
rotatedPointer.MakeTransparent(Color.White);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(rotatedPointer, 0, 0);
?????????????
}
Now, I want to send my finalImage without saving it on the disk with Save method.
How can I?
Thanks in advice!
Save it to MemoryStream, and send the MemoryStream in your call to the bot, like this:
using (MemoryStream ms = new MemoryStream())
using (Bitmap finalImage = new Bitmap(speedometer))
{
using (Graphics graphics = Graphics.FromImage(finalImage))
{
// ... stuff
}
finalImage.Save(ms, ImageFormat.Png);
// This is important: otherwise anything reading the stream
// will start at the point AFTER the written image.
ms.Position = 0;
Bot.SendPhotoAsync(/* send 'ms' here. Whatever the exact args are */);
}
It is possible that async sending requires the stream to remain open. Though, normally, when you have such an async send, you can specify a function that should be called after the sending has finished.
In that case, you should not put the MemoryStream in a using block, but instead store the stream object in a global variable in your class, and make sure that the function handling the end of the async send disposes it.
Also do note this question...
bot.sendphoto does not work asp.net
Apparently SendPhotoAsync is not enough to actually send it; the answer there specifies you need to call .GetAwaiter() and .GetResult(). I don't know the API, so you'll have to figure that out yourself.
From the Telegram Bot API documentation (link)
Sending files
There are three ways to send files (photos, stickers, audio, media, etc.):
...
Post the file using multipart/form-data in the usual way that files are uploaded via the browser. 10 MB max size for photos, 50 MB for other files.
Your question is not clear!
However, (if I understand your question right)
You are using TelgramBotClient from this repository: https://github.com/TelegramBots
when you invoke SendPhotoAsync from this client it takes FileToSend as a parameter which represent the photo you processed with rotation, transparency and smoothing.
when you pass this FileToSend you can set the photo either by loading it from temp file you created after processing or you can load it directory from MemoryStream like this:
using System.Drawing;
using System.Drawing.Drawing2D;
using Telegram.Bot;
using Telegram.Bot.Args;
using System.IO;
using System.Drawing.Imaging;
namespace LoadGraphicsFromMemory
{
public static class ImageExtensions
{
public static MemoryStream ToMemoryStream(this Bitmap image, ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, format);
return ms;
}
}
}
class Program
{
private static float efficienza_int;
private static readonly TelegramBotClient Bot = new TelegramBotClient("Your API key");
static void Main(string[] args)
{
Bot.OnMessage += BotOnMessageReceived;
}
private static void BotOnMessageReceived(object sender, MessageEventArgs e)
{
Bitmap speedometer = new Bitmap(#"C:\Immagini\bot\speedometer.png");
Bitmap pointer = new Bitmap(#"C:\Immagini\bot\pointer.png");
Bitmap finalImage = new Bitmap(speedometer);
using (Graphics graphics = Graphics.FromImage(finalImage))
{
Bitmap rotatedPointer = RotateImage(pointer, efficienza_int * (float)1.8);
rotatedPointer.MakeTransparent(Color.White);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(rotatedPointer, 0, 0);
}
Bot.SendPhotoAsync(e.Message.Chat.Id, new Telegram.Bot.Types.FileToSend("My File", finalImage.ToMemoryStream(ImageFormat.Jpeg)));
}
private static Bitmap RotateImage(Bitmap pointer, object p)
{
return pointer;
}
}
}

How do I get the dimensions of an image synchronously in a UWP app?

I am trying to get an image's dimensions before I display it in the OnLoaded() method. I want to do this synchronously (not asynchronously) because I need to know the image's dimensions before the program continues. I'm making a mapping program where the coordinates, scale and translation offset of the background image are important and are all dependent on knowing the image's dimensions from the very beginning of the app.
I have read most of the msdn documentation on StorageFile, SoftwareBitmap, and asynchronous method calls along with trying many methods I have found online with no success.
https://msdn.microsoft.com/en-us/windows/uwp/threading-async/asynchronous-programming-universal-windows-platform-apps
https://msdn.microsoft.com/en-us/windows/uwp/threading-async/call-asynchronous-apis-in-csharp-or-visual-basic
Basically I am looking for a synchronous c# function that takes the uri of an image file and returns a Point containing the dimensions. i.e.
public Point getImageDimensions(Uri u){...}
This function is so easy to implement in Android apps, I don't understand why it is so difficult in UWP apps.
I can provide more details if needed, thanks in advance.
I get the following error with this code:
Exception thrown: 'System.Exception' in App1.exe
Exception thrown: 'System.AggregateException' in mscorlib.ni.dll
App1.xaml.cs
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Shapes;
namespace App1
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.Loaded += OnLoaded;
Point p = Task.Run(() => getImageDimensions("ms-appx:///Assets/NewSpaceBackground.png")).Result;
Debug.WriteLine("p.X: " + p.X + " p.Y: " + p.Y);
}
void OnLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Rectangle backgroundRect1 = new Rectangle();
ImageBrush imgBrushBackground1 = new ImageBrush();
imgBrushBackground1.ImageSource = new BitmapImage(new Uri(#"ms-appx:///Assets/NewSpaceBackground.png"));
backgroundRect1.Fill = imgBrushBackground1;
//backgroundMap.Add(backgroundRect1);
}
public async Task<Point> getImageDimensions(string strURI)
{
Point p;
StorageFile photo;
try
{
var uri = new Uri(strURI);
photo = await StorageFile.GetFileFromApplicationUriAsync(uri);
}
catch (Exception e)
{
Debug.WriteLine(e.StackTrace);
return p;
}
//read in the bitmap stream
IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
//convert the image to a bitmap
SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);
//print out the dimensions
Debug.WriteLine(softwareBitmapBGR8.PixelWidth + " " + softwareBitmapBGR8.PixelHeight);
p.X = softwareBitmapBGR8.PixelWidth;
p.Y = softwareBitmapBGR8.PixelHeight;
return p;
}
}
}
I am trying to get an image's dimensions before I display it in the OnLoaded() method. I want to do this synchronously (not asynchronously) because I need to know the image's dimensions before the program continues.
There are some problems when you want to call async functions in constructor, for details you can refer to Stephen Cleary's blog: Async OOP 2: Constructors.
In UWP, You can put the Page initialization codes (getImageDimensions and the codes of displaying the image) in Page.OnNavigatedTo method and use await in it:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
Point p = await getImageDimensions("ms-appx:///Assets/NewSpaceBackground.png");
Debug.WriteLine("p.X: " + p.X + " p.Y: " + p.Y);
Rectangle backgroundRect1 = new Rectangle();
ImageBrush imgBrushBackground1 = new ImageBrush();
imgBrushBackground1.ImageSource = new BitmapImage(new Uri(#"ms-appx:///Images/image03.jpg"));
backgroundRect1.Fill = imgBrushBackground1;
...
}
Update:
Would you recommend an easier, synchronous, way to get the dimensions?
Most of the file related operations are designed to be async, user can use/not use await to choose to do the operation sychronously or asynchronously.
There is indeed an easy way to obtain the image's dimension:
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///images/image01.png"));
var properties=await file.Properties.GetImagePropertiesAsync();
var width = properties.Width;
var height = properties.Height;
Instead of streaming it into a Bitmap, could you load it into a System.Drawing.Image, like so?:
System.Drawing.Image img = System.Drawing.Image.FromStream(myStream);
Then you have access to the System.Drawing.Image's Size property, which should give you what you need, as well as easy access to resizing. All of this is available in .NET Core and UWP if memory serves.

How to convert an SVG file to an EMF file in C#

It's definitely possible to convert an SVG to EMF, for example this website. I wonder if it's possible to achieve this conversion in C#?
Update:
I tried to read an SVG file using SVG.NET and draw it to a Graphics object, then tried export the Image as a MetaFile in .emf extension (I followed the instruction here: GDI+ / C#: How to save an image as EMF?). The reading was done successfully and the image did get exported as .emf. However, when I opened that .emf in PowerPoint, it couldn't be un-grouped, which indicated that the drawing info of that file was actually not dumped correctly.
Update 2:
Now it does export a ungroup-able .emf, but the ungrouping shows a really poor result. I used the following code to produce the .emf:
private void OpenPictureButtonClick(object sender, EventArgs e)
{
var openFileDialog = new OpenFileDialog();
openFileDialog.ShowDialog();
_svgDoc = SvgDocument.Open(openFileDialog.FileName);
RenderSvg(_svgDoc);
}
private void SavePictureClick(object sender, EventArgs e)
{
var saveFileDialog = new SaveFileDialog {Filter = "Enhanced Meta File | *.Emf"};
saveFileDialog.ShowDialog();
var path = saveFileDialog.FileName;
var graphics = CreateGraphics();
var img = new Metafile(path, graphics.GetHdc());
var ig = Graphics.FromImage(img);
_svgDoc.Draw(ig);
ig.Dispose(); img.Dispose(); graphics.ReleaseHdc(); graphics.Dispose();
}
private void RenderSvg(SvgDocument svgDoc)
{
svgImageBox.Image = svgDoc.Draw();
}
I had the same issue but searching had no results.
Finally I ended up with my own simple solution below. I used SVG.NET.
public static byte[] ConvertToEmf(string svgImage)
{
string emfTempPath = Path.GetTempFileName();
try
{
var svg = SvgDocument.FromSvg<SvgDocument>(svgImage);
using (Graphics bufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero))
{
using (var metafile = new Metafile(emfTempPath, bufferGraphics.GetHdc()))
{
using (Graphics graphics = Graphics.FromImage(metafile))
{
svg.Draw(graphics);
}
}
}
return File.ReadAllBytes(emfTempPath);
}
finally
{
File.Delete(emfTempPath);
}
}
At first I create a temp file. Then I use Draw(Graphics) method to save emf in it. And at last I read bytes from temp file.
Don't try to use MemoryStream for Metafile. Unfortunately, it's not working.
This is what I found to be currently the best solution. This is almost like the accepted answer and uses SVG.NET, but is capable of doing it in memory.
The important changes are to release the handle and to reset the position memory stream.
public static Stream ConvertSvgToEmf(string svgImage)
{
using var writeStream = new MemoryStream();
var svg = SvgDocument.FromSvg<SvgDocument>(svgImage);
var stream = new MemoryStream();
var sizedImage = new Bitmap((int)svg.Width.Value, (int)svg.Height.Value);
using (var graphicsFromSizedImage = Graphics.FromImage(Image.FromHbitmap(sizedImage.GetHbitmap())))
using (var metafile = new Metafile(stream, graphicsFromSizedImage.GetHdc(), EmfType.EmfPlusOnly)) // Specify EmfType for lesser file size
using (var graphics = Graphics.FromImage(metafile))
{
svg.Draw(graphics);
graphicsFromSizedImage.ReleaseHdc();
}
stream.Position = 0;
return stream;
}
Be aware that the underlying implementation relies on System.Drawing and therefore the gdi must be accessible. On linux based OS's (or Docker images) libgdiplus must be installed.
As System.Drawing is considered to be deprecated, alternatives like Magick.NET may be better suited for your case.

Windows Phone ScheduleAgent grabbing images on set period

I'm attempting to follow an Windows Phone tutorial, tweaking it a bit to fit my needs. I am trying to grab a new picture every X seconds (30 for debugging) and set it as the new lockscreen background. I created a ScheduleAgent object to call it, however, it seems to be skipping a function. It does not skip this when in the MainPage.xaml.cs, which runs the exact same function.
ScheduleAgent.cs
static ScheduledAgent()
{
....<irrelevant code>....
protected override void OnInvoke(ScheduledTask task)
{
.... < Code went here that shouldn't matter > ....
}
Debug.WriteLine("Imagename = " + imageName);
DownloadImagefromServer("https://s3-us-west-2.amazonaws.com/qoutescreen/0" + imageName + ".jpg");
m.ReleaseMutex();
}
// If debugging is enabled, launch the agent again in one minute.
// debug, so run in every 30 secs
#if(DEBUG_AGENT)
ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(30));
System.Diagnostics.Debug.WriteLine("Periodic task is started again: " + task.Name);
#endif
// Call NotifyComplete to let the system know the agent is done working.
NotifyComplete();
}
//===============================================================================
private async void LockScreenChange(string filePathOfTheImage, bool isAppResource)
{
if (!LockScreenManager.IsProvidedByCurrentApplication)
{
// If you're not the provider, this call will prompt the user for permission.
// Calling RequestAccessAsync from a background agent is not allowed.
await LockScreenManager.RequestAccessAsync();
}
// Only do further work if the access is granted.
if (LockScreenManager.IsProvidedByCurrentApplication)
{
// At this stage, the app is the active lock screen background provider.
// The following code example shows the new URI schema.
// ms-appdata points to the root of the local app data folder.
// ms-appx points to the Local app install folder, to reference resources bundled in the XAP package
var schema = isAppResource ? "ms-appx:///" : "ms-appdata:///Local/";
var uri = new Uri(schema + filePathOfTheImage, UriKind.Absolute);
// Set the lock screen background image.
LockScreen.SetImageUri(uri);
// Get the URI of the lock screen background image.
var currentImage = LockScreen.GetImageUri();
System.Diagnostics.Debug.WriteLine("The new lock screen background image is set to {0}", currentImage.ToString());
}
}
private async Task DownloadImagefromServer(string imgUrl)
{
Debug.WriteLine("Attempting to Get Image from Server...");
WebClient client = new WebClient();
try
{
// I GET A "Cannot await Void" problem here?!?!?
//=================================================================
var result = await client.OpenReadAsync(new Uri(imgUrl, UriKind.Absolute));
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(result);
return result;
}
catch (Exception e)
{
Debug.WriteLine(e);
}
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
//client.OpenReadAsync(new Uri(imgUrl, UriKind.Absolute));
}
//------------------------------------------------------------------
//THIS FUNCTION IS NEVER HIT WHEN RUN IN THE ScheduleAgent.cs CODE, HOWEVER
// WHEN IT IS RUN INT HE MainPage.xaml.cs CODE (Which is a copy/paste) IT RUNS FINE
// WHY IS IT NOT HITTING THIS? HOW CAN I FIX IT?
//------------------------------------------------------------------
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(e.Result);
//img.Source = bitmap;
// Create a filename for JPEG file in isolated storage.
String tempJPEG = "DownloadedWalleper.jpg";
// Create virtual store and file stream. Check for duplicate tempJPEG files.
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(tempJPEG))
{
myIsolatedStorage.DeleteFile(tempJPEG);
}
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(tempJPEG);
StreamResourceInfo sri = null;
Uri uri = new Uri(tempJPEG, UriKind.Relative);
sri = Application.GetResourceStream(uri);
//BitmapImage bitmap = new BitmapImage();
//bitmap.SetSource(sri.Stream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
//wb.SaveJpeg(fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
LockScreenChange("DownloadedWalleper.jpg", false);
}
}
I would recommend using the "await" keyword. This will cause the code to pause and wait for the action to complete without needing to worry about mutexes or other thread-blocking strategies.
Unfortunately Windows Phone is missing the non-async methods on WebClient, so there's a little bit of setup, blatantly stolen from this answer.
To use async with WebClient, install the Microsoft.Bcl.Async NuGet package, and then you can use OpenReadTaskAsync
private async void DownloadImagefromServer(string imgUrl)
{
Debug.WriteLine("Attempting to Get Image from Server...");
WebClient client = new WebClient();
var result = await client.OpenReadTaskAsync(new Uri(imgUrl, UriKind.Absolute));
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(result);
//img.Source = bitmap;
... rest of your code from OpenReadCompleted goes here
}
So what happens is that execution waits for the "OpenRead" call to complete before it processes the result and then returns control.

creating a file in isolated storage wp7

I am using following code to create a file in isolated storage
mystorage = IsolatedStorageFile.GetUserStoreForApplication();
if (mystorage.FileExists(scanName))
{
mystorage.DeleteFile(scanName);
}
WriteableBitmap wb = new WriteableBitmap(canImage, null);
using (MemoryStream stream = new MemoryStream())
{
wb.SaveJpeg(stream, (int)canImage.Width, (int)canImage.Height, 0, 100);
using (IsolatedStorageFileStream local = new IsolatedStorageFileStream(scanName, FileMode.Create, mystorage))
{
local.Write(stream.GetBuffer(), 0, stream.GetBuffer().Length);
}
}
if (MessageBox.Show("Scan updated successfully") == MessageBoxResult.OK)
{
App.isTransformRequest = false;
NavigationService.Navigate(new Uri("/View/EditDocument.xaml?paramList=" + App.currentName, UriKind.RelativeOrAbsolute));
}
this code works fine. But I want to detect weather the file is completely created or not, and after that only I want to display the success message. The way I am currently working somtimes displays the success message before the complete creation of the file, I want the message to be displayed only after the file is created completely, ie the stream is written completely.
Using the BeginWrite Method of the IsolatedStorageFileStream (msdn) you can regsiter a ActionCallback to continue with the redirection options in your UI.
Please note, if your callback shows a MessageBox in the UI-Thread, you have to sync the ThreadContext using the Dispatcher (msdn)

Categories