BitmapSource to point to local file - c#

What's the best pattern to implement a local cache for a Metro Style App so that the images can be cached in the background while the app is being used on-line and to serve images when the App goes offline?
How do we set a BitmapSource to a local file upon discovering the lack of internet access? using new Uri(localpath, UriKind.Absolute) doesn't work.

Are the images already downloaded? If so, are they in the "Local" folder?
If so, you can build a BitmapImage from the path like this
var m_Image = new BitmapImage(new Uri("ms-appdata:///local/" + ImageFileName));
EDIT
If your file is stored in the package as a "never had access and can't download anything" standby, the Uri would be something like
var m_Image = new BitmapImage(new Uri("ms-appx:///Assets/" + FallBackImageFileName));

Related

C# UWP app crashes if SecondaryTile Imagesources are not from Assets folder

Basically I'm trying to make an UWP app to create Custom Tiles on Start Menu.
The SecondaryTile is working when the Tile Images are from Assets folder like this.
Uri square150x150Logo = new Uri("ms-appx:///Assets/square150x150Tile-sdk.png");
Uri wide310x150Logo = new Uri("ms-appx:///Assets/wide310x150Tile-sdk.png");
Uri square310x310Logo = new Uri("ms-appx:///Assets/square310x310Tile-sdk.png");
Uri square30x30Logo = new Uri("ms-appx:///Assets/square30x30Tile-sdk.png");
But I have images in ApplicationData folders and trying to use the path like this:
Uri square150x150Logo = new Uri(Path.Combine(ApplicationData.Current.TemporaryFolder.Path, "ImageSquare.png"));
Uri wide310x150Logo = new Uri(Path.Combine(ApplicationData.Current.TemporaryFolder.Path, "ImageWide.png"));
Uri square310x310Logo = new Uri(Path.Combine(ApplicationData.Current.TemporaryFolder.Path, "ImageLarge.png"));
Uri square30x30Logo = new Uri(Path.Combine(ApplicationData.Current.TemporaryFolder.Path, "ImageTiny.png"));
But this way the app is crashing. The debugger isn't working either. Any solutions?
To reference application data files, you should be using ms-appdata:///.
Calling TemporaryFolder.Path will return the absolute file path, C:\, which isn't allowed to be used on secondary tiles.
So your updated code would be...
Uri square150x150Logo = new Uri("ms-appdata:///temp/ImageSquare.png"));
OK finally figured it out.
In Addition to Andrew's answer, I had to change to using the LocalState folder instead of the TempState.
Andrew directed in the right way to use ms-appdata, but for some reason ms-appdata:///temp/ returned error. but using ms-appdata:///Local/ solved the Issue.

c# WPF URI syntax

I am just learning c# and have been struggling to work with URIs in WPF. I've googled around a fair bit but not having much luck.
Essentially I'm trying to have a BitmapImage object stored as a property in a Car object. I then want to display the BitmapImage in an Image control on a WPF form.
The app is a simple app (it's for a Uni assignment), so no database, etc.
I have two methods of doing this. The first is that I'm preloading Car data from a text file, including the filename of the JPG I want to load. I have included the JPG in a directory called Files which is off the main directory where my source code and class files are. I have set the JPG file to 'Content' and 'Always copy'. When I run a Debug, it copies the Files directory and the JPG to the debug\bin directory.
My code creates a BitmapImage by referring to the JPG using a URI as follows;
BitmapImage myImage = new BitmapImage (new Uri("Files/" + Car.Imagefilename, UriKind.Relative);
Car.Image = myImage;
ImageControl.Source = myImage;
If I step through this code in the debugger, it sometimes works and displays the image, but most of the time it doesn't.
My second method is when a user creates a new Car. This method always works. In this one, I use a file dialog box (dlg) to select the image and use an absolute path.
BitmapImage myImage = new BitmapImage (new Uri(dlg.Filename, UriKind.Absolute);
Car.Image = myImage;
ImageControl.Source = myImage;
So....I can't work out why the first method doesn't work. I think it's got something to do with the relative reference, but I can't work out how to syntax that properly to work. I've tried using "pack:,,,", I've tried adding "component", I've tried an '#' before the "pack". I can't seem to find something that explains this simply.
Apologies if this is straight forward but it's doing my head in! Appreciate any pointers.
If the image files are located in a "Files" folder of your Visual Studio project, you should set their Build Action to Resource (and Copy to Output Directory to Do not copy), and load them by a Resource File Pack URI:
var image = new BitmapImage(new Uri("pack://application:,,,/Files/" + Car.Imagefilename));
Car.Image = image;
ImageControl.Source = image;
There is no need to copy the files anywhere. Images are loaded directly from the assembly.
First try to load the image file using its absolute path. For example if the images are stored in c:\projects\yourproject\files, then try using something like
BitmapImage myImage = new BitmapImage (new Uri("c:/projects/yourproject/files/carname.jpg", UriKind.Absolute);
If it works, what you are facing is an path calculation issue.
At this point you may either calculate the Absolute with reference to your executable using AppDomain.CurrentDomain.BaseDirectory at runtime or use App.Config to store the path and reference it from there.
Cheers

BitmapImage and Uri for local file (WinRT store app)

I am attempting to display an image that lives on my c: drive. The code below shows how I handle two images: image 1 is local and image 2 is from the web.
Image 1 fails to display, image 2 works perfectly. Why does image 1 fail to display?
private void Button_Click(object sender, RoutedEventArgs e)
{
// Image 1 - lives on local disk
var uri = new Uri(#"C:\Users\Frank\Pictures\MindMap.jpg", UriKind.Relative);
BitmapImage img = new BitmapImage(uri);
testImage.Source = img;
// Image 2 - image lives on web
var uri2 = new Uri("http://www.mommyish.com/wp-content/uploads/2013/05/GwynethPaltrow.jpg");
BitmapImage img2 = new BitmapImage(uri2);
testImage2.Source = img2;
}
You can't do this. Because app have limited access to the device/computer. This can be understand from this - for accessing Pictures library photos you have to add the capability to your app explicitly. You can understand this - as for security reasons too.
Suppose it has been displayed correctly but after some days someone has deleted it. then what happen to your app. It will crash. Or you can say app become dependent on the device to work.
So it is better that you understand the domain of an app and resources and capabilities of an app that is can use.
So first add image to your YourAppFoder then access it.

SL 5 Out of Browser, Elevated Trust - Display PNG From Any LOCAL Directory

My understanding is that when I set SL5 to run OOB and elevated trust that I should have wide open access to any directory/file on the local system. If an external system places png image files into the user's c:\images folder, how can I load the various png files into a XAML Image element?
This line works:
image.UriSource = new Uri(value as string);
if I set value to a string like "http://blah.com/image1.png"
But fails if I try to set it to:
ImageUrl = new Uri(#"C:\images\image3.png")
which gets resolved to something like "file:///C:....." when it hits the
image.UriSource = new Uri(value as string);
line.
How do I display png files in SL5 from any local path on the system running the OOB elevated app?
Something like this should work provided that you have elevated permissions set correctly
var bmp = new BitmapImage();
var stream = new FileStream(#"c:\dir\folder\image.png", FileMode.Open);
bmp.SetSource(stream);
stream.Close();
If you need to use a uri, this should work:
var bmp = new BitmapImage();
var uri = new Uri("c:/dir/folder/image.png");
bmp.UriSource = uri;
Note that the paths are different. The uri path requires forward slashes to be used.
You can then set the source of your image control to the bmp
image.Source = bmp;
If you're getting a 'File Operation not permitted' exception you need to double check that elevated permissions is checked in your out of browser settings
Project -> Properties -> 'Out of browser settings'
Check 'Require elevated trust...'

C# - WPF how to unreference a BitmapImage so I can delete the source file?

This seems like a fairly simple issue, but I can't seem to figure a way to work around it.
In a WPF window I have an image, image_small_pic. In the associated C# file I set the value of that using this code:
Uri src = new Uri(image_source, UriKind.RelativeOrAbsolute);
small_image_bmp = new BitmapImage(src);
image_small_pic.Source = small_image_bmp;
Where small_image_bmp is a public BitmapImage object. But then if then, later on, if I change small_image_bmp to another file and reassign image_small_pic.Source, then the original image is still locked and I can't delete it. Even if I try later it's still locked. Any thoughts how I can free this up?
Check out this article. There's some odd behaviour with WPF images that you're coming across. The solution is to read in the bytes yourself and then create an image based on them, since if you let the framework handle it, the file will remain locked.
Uri src = new Uri(image_source, UriKind.RelativeOrAbsolute);
var small_image_bmp = new BitmapImage();
small_image_bmp.BeginInit();
small_image_bmp.CacheOption = BitmapCacheOption.OnLoad;
small_image_bmp.UriSource = src;
small_image_bmp.EndInit();
image_small_pic.Source = small_image_bmp;

Categories