Null Reference Exception when StreamResourceInfo attempts to get a ResourceStream? - c#

I'm following one of the MSDN Introduction to Windows Phone Development labs, and have run into a problem with this lab (Introduction to Controls Available for Windows Phone Applications). The lab provides both the starting files, and the end files (i.e., what the program should look like upon completion of the lab).
The particular part of the lab that has me stumped is the point where I'm reading in a series of images from an Assets folder, then displaying them in a ListBox on screen. Whenever this code tries to run, it throws a Null Reference Exception:
public static BitmapImage GetImage(string filename)
{
string imgLocation = Application.Current.Resources["ImagesLocation"].ToString();
StreamResourceInfo imageResource = Application.GetResourceStream(new Uri(imgLocation + filename, UriKind.Relative));
BitmapImage image = new BitmapImage();
image.SetSource(imageResource.Stream);
return image;
}
I've dug into as much as I can, and imageResource always winds up Null somehow, and I can't for the life of me figure out where it's going wrong.
I've included a link to the two projects here (129 MB, sorry for that). Everything under the "Begin" folder is what I've done so far (and throws an Exception when I attempt to navigate to the Images page during runtime). Everything under the "End" folder is what it's supposed to end up looking like, and is functional.
I'm very new to C# and WP7 development, so any help would be greatly appreciated. Thank you!

Try to change the build for the .bmp to "Resource".
Here's a couple of links explaining it:
http://forums.silverlight.net/t/238891.aspx/1
Application.GetResourceStream called on a Content Resource still return null

The problem is that when you set your images directory in App.xaml file, there is a mistake in the tutorial. You should set the application resource, ImagesLocation like this:
<system:String x:Key="ImagesLocation">Begin;component/Assets/Images/</system:String>
Where Begin is your project name ;component/ is needed as separator, and finally the Assets/Images/ is the relative path to your images directory.

Related

Flip View Data Binding and file permissions

I am learning the basics of UWP and app making in Windows 10.
I am trying to make a flip view with data that is pulled off a folder. It didn't display any images, so I tried manually adding images like so,
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/1.png")));
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/2.png")));
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/jpg.jpg")));
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/jpeg.jpeg")));
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/jpg.png")));
PrivateSet_images.Add(new BitmapImage(new Uri("ms-appx:///Assets/Spot/jpeg.png")));
PrivateSet_images.Add(new BitmapImage(new Uri("F:\\Test Sp Folder\\1.png")));
PrivateSet_images.Add(new BitmapImage(new Uri("F:/Test Sp Folder/1.png")));
All the ms-appx assets are read and displayed successfully (so not a file-type / file-extension problem). As for permissions to the folder, I used a folder picker to access a few files, so there are no permission issues (as described here). I checked the debugger, and the files are read properly, but the last two aren't displayed (which point to the same file, I wanted to make sure it wasn't the '/' or '\\' preventing them from being displayed.)
XAML Code:
<FlipView x:Name="FlipViwe" ItemsSource="{x:Bind ViewModel.Images}" Visibility="Visible">
<FlipView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Stretch="Fill"/>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
I don't seem to be able to solve this with solutions or similar questions like Bind a Collection as ItemsSource, Flipview not showing any pictures and Show image files from a directory in a Flipview
What am I missing?
Thank You.
The UWP apps do not have permission to access all files on the device. By default, apps can access certain file system locations such as application install directory or application data locations. For more info, please see File access permissions.
"F:\Test Sp Folder\1.png" is a location that you app can't directly access. While dealing with files or folders in UWP, one important rule is Skip the path: stick to the StorageFile.
It is recommend to use a Folder​Picker to let the user pick the folder and add it to your app's FutureAccessList or MostRecentlyUsedList, in this way the they can be reloaded later without requiring the user to go through the picker. For more information, please check: How to track recently-used files and folders.
Okay,
So with the answer form #Jayden, I managed to find a solution.
Here goes,
In a UWP app, using direct paths to files *may fail, reasons being either permissions, or the path being, as I like to put it, 'Virtual Directory'. One example is the Photos or the Music collection. All the files are populated and 'sent' to the requesting app. Also, the files may be from an another app. So storing the strings is pointless.
Protected view for files is provided by the StorageItems classes (i.e. StorageFolder and StorageFile). StorageItems are the canonical storage identifiers for Windows Store apps, not the path. Your life (and your app) will be easier if you think and work in terms of StorageItems rather than trying to convert back and forth between StorageItems and paths. A key property of the StorageFile is that it isn’t restricted to file system objects. For example, a StorageFile can represent a photo “file” the user selected from another app via the file picker contract . The app deals with the StorageFile and doesn’t need to know or care if the data originated on disk or in another app. Conversely, apps which demand to know where the data originated can run into trouble: the StorageFile may not have a Path or may have a non file-system path.
So to overcome that, one has to use StorageFile, that guarantees access to files (assuming you already have permissions to it). Also remember to store your access-permission!
The Windows.Storage.AccessCache namespace provides classes to remember StorageItems so they can be reloaded later without requiring the user to go through the picker. The StorageApplicationPermissions.FutureAccessList provides random access to items that have been previously used. The MostRecentlyUsedList allows keeping a list of recently used locations.
After going through multiple examples and countless trials, I hit upon the solution, which I realized is similar to a linked question.
public async void ImageViewGenerateAsync () {
var ImagesFolder = await StorageApplicationPermissions.
FutureAccessList.GetFolderAsync("FolderFoken");
var ImgFiles = await ImagesFolder.GetFilesAsync();
foreach( StorageFile file in ImgFiles ) {
if (file != null ) {
try {
var filestream = await file.OpenAsync(FileAccessMode.Read);
var img = new BitmapImage();
await img.SetSourceAsync (filestream);
PrivateSet_images.Add(img);
}
catch ( Exception ) {
}
}
}
It, instead of accessing the files through strings and Uri, uses StorageFile that handles giving the file to you. Then read the files through OpenAsync and set this stream as the source of the BitmapImage (Described here, scroll down to Using a stream source to show images from the Pictures library). I'm not sure of this is an optimized solution, but it works. I'd love to see if there is a better and optimized solution.
XAML:
<FlipView x:Name="FlipViweSpotlight" ItemsSource="{x:Bind ViewModel.Images}" Visibility="Visible">
<FlipView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Stretch="Uniform"/>
</DataTemplate>
</FlipView.ItemTemplate>
This is a rudimentary solution that I came up with, any improvements / optimizations would be welcome!
Thanks!

Difference between #"pack://application:,,,[...] and IO.Directory.GetCurrentDirectory()?

I've noticed that when I add a line of <Window.Background></Window.Background> in the XAML file or in the C# code this.Background = new ImageBrush(new BitmapImage(new uri([...])); if I put in the "Uri" this: new Uri(#"pack://application:,,,/Myapp;component/image.jpg") I get an error when I try to compile it which says: "Could not locate resource "image.jpg" "
But if I change this to new Uri(System.IO.Directory.GetCurrentDirectory()+"\\image.jpg"); it never gives me an error. Why???? What is the difference between both methods? I am very comfortable with Directory but why the compiler doesn't show an error "Locating" the resource with IO.Directory? What's the difference?
The questions may sound too noob, but I don't understand why it gives an error in #"pack://application[...] and not with GetCurrentDirectory()
A pack:// Uri, will search embedded resources for the image. The resources are inside the DLL/EXE, rather than deployed to the same folder. To use an image as a WPF Resource you need to set the Build Action on the image to Resource.
Using the Directory approach simply searches the physical file system for the image.
More info here on WPF Pack Uri's.

Having Trouble Accessing an Embedded Resource [duplicate]

I have a game application in Visual Studio 2012 C#. I have all the .png images I am using in the Resources file of the project.
Have you any idea why I can access all the files but one by using Properties.Resources?
I checked the full filePath and it's set to the resources folder. And it's added in the program as I did Add -> Existing Item and added the image.
It looks just like the other images. I have no idea why it's not loading. I need this since I need to send a .exe by email to my lecturer and without this image the project is nothing!
I added this in the resource file
internal static System.Drawing.Bitmap grid_fw {
get
{
object obj = ResourceManager.GetObject("grid.fw", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
and although now grid is available, it is returning null :/
Found from: Properties.Resources the icon name does not appear in the intellisense
You also need to add the icon to the Resources.resx file. Open it in
Visual Studio and drag your icon into the Icons menu of the resx and
it will become available.
Also, see Adding and Editing Resources (Visual C#)
You can get a reference to the image the following way:
Image myImage = Resources.yourImage;
If you want to make a copy of the image, you'll need to do the following:
Bitmap bmp = new Bitmap(Resources.yourImage);
Don't forget to dispose of bmp when you're done with it. If you don't know the name of the resource image at compile-time, you can use a resource manager:
ResourceManager rm = Resources.ResourceManager;
Bitmap yourImage = (Bitmap)rm.GetObject("yourImage");
The benefit of the ResourceManager is that you can use it where Resources.myImage would normally be out of scope, or where you want to dynamically access resources. Additionally, this works for sounds, config files, etc.

Portability worries because of custom cursor path in C#

I am using a custom cursor named hand2.cur in my C#-WPF application. I have added the cursor to a folder named Images which has all the images that I use in my application. However I've realized that I cannot add relative path to use my custom cursor as:
Cursor newCur = new Cursor("Images\\hand2.cur");
window.Cursor = newCur;
So I used this:
string absolute = System.IO.Path.GetFullPath("hand2.cur");
Cursor newCur = new Cursor(absolute);
window.Cursor = newCur;
This tries to find the hand2.cur file in the \bin\Release folder. So I added the file there and I got it working.
But the problem is, if I Publish this application and use it on a different computer, it does not work. Now the problem is with the cursor file path, because if I deploy it after commenting those 3 lines, it works correctly. So what do I do to rectify this problem?
I am using other images from the Image folder in my XAML code and they seem to port fine. But then again my knowledge of WPF is limited so if anyone has any ideas, that would help.
EDIT: I have added my Images folder to the project. I have also set the Build Action of the cursor file hand2.cur to Embedded Resource. However when I use the following two lines, I get an XAMLParseException.
System.Windows.Resources.StreamResourceInfo info = Application.GetResourceStream(new Uri("pack://application:,,,/Slideshow;component/Images/hand2.cur"));
window.Cursor = new System.Windows.Input.Cursor(info.Stream);
The Inner Exception field when I view the details of the error reads: {"Cannot locate resource 'images/hand2.cur'."}
You could make the cursor a resource in your app/assembly and then use GetResourceStream with the pack Uri to the resources location. Pass the Stream of the StreamResourceInfo to the ctor of the Cursor. e.g.
var info = Application.GetResourceStream(new Uri("pack://application:,,,/Images/hand2.cur"));
var cursor = new Cursor(info.Stream);
I've got this working after I added the cursor file hand2.cur to my Resource1.resx resource file. Then I used the following statement in my code:
window.Cursor = new Cursor(new System.IO.MemoryStream(MyNameSpace.Resource1.hand2));

PNG and jpg images not appearing in C# application

I have a problem with displaying certain images in my application using C#. I am using the Image class to specify the location and the BitmapImage to specify the source. The UriSource is relative and I just specify the name. It worked for some images, but for others, the image simply does not appear. My image instance is 35x35 big and another is 100x100 big (pixels).
Anyone knows why this might be occurring and how to fix it?
Thanks.
Here's the code I used:
Image removeImage = new Image();
removeImage.HorizontalAlignment = HorizontalAlignment.Left;
removeImage.VerticalAlignment = VerticalAlignment.Top;
removeImage.Margin = new Thickness(490, 10, 0, 0);
removeImage.Width = 35;
removeImage.Height = 35;
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = new Uri("delete.png", UriKind.RelativeOrAbsolute);
source.EndInit();
removeImage.Source = source;
removeImage.Stretch = Stretch.None;
removeImage.Visibility = Visibility.Visible;
removeImage.MouseDown += new MouseButtonEventHandler(removeImage_MouseDown);
Not sure about the location of image files. If images are in your current project folder then you have to set Copy To Output Directory=Copy Always property of image file from Properties Windows.
The best way that I know of to diagnose a problem like that (assuming a quick peer review of the code gets you nowhere), is to use ProcessMonitor: http://technet.microsoft.com/en-us/sysinternals/bb896645
You can use this tool to monitor all of the file activity on your machine (make sure to use the include/exclude filters to limit the noise).
It's very likely that the reason that the images are not showing up is because your application is looking for them in the wrong place (either they didn't get copied, or the relative path is off).
ProcessMonitor will log every attempt that Windows makes to access your .jpg (whether it fails or succeeds). If you search for your file name in the log, you should find it, probably along with an error message, and the full path that Windows was using to open the file.
The most common results I see are
Path that was actually being used was different from the path you needed.
The path was correct, but your files weren't there (build/copy/install problem)
The path was correct, but your web app did not have permissions to read the file.
In all those cases, ProcessMonitor will show you what happened.

Categories

Resources