Update an image source when pressing a button - c#

I have a problem with Uri and my image file.
I tested a lot of things on how to make it work but without success.
(I have image A on start. I click on image and image A change to B.)
Please can anyone expain me this problem?
I know here is lot questions about this but i still dont understand it.
Thx in advance
XAML:
<Image x:Name="obr_0_1" Grid.ColumnSpan="1"
Grid.Column="0" Grid.Row="0"
Tapped="obr_0_1_Tapped" Loaded="obr_0_1_Loaded"/>`
C#:
private void obr_0_1_Tapped(object sender, TappedRoutedEventArgs e)
{
zmenObrazek();
}
private void zmenObrazek()
{
obr_0_1.Source = new BitmapImage(new Uri("/Content/Obrazky/half-life.png", UriKind.Relative));
}
When I set the source this way, I get:
An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not > handled in user code
How do I set the image source from code ?

What about implementing the following static class:
using System;
using System.IO;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
// I don't know your namespace but put it in the same namespace as your code above
// (or reference this namespace in your code above)
namespace MyNamespace
{
public static class Helper
{
public static Image CreateImage(string fileName, int desiredPixelWidth)
{
Image myImage = new Image();
//set image source
myImage.Source = CreateSource(fileName);
myImage.Width = desiredPixelWidth;
return myImage;
}
public static BitmapImage CreateSource(string fileName)
{
var file = new FileInfo(fileName);
System.Drawing.Image im = System.Drawing.Image.FromFile(file.FullName);
int actualPixelWidth = im.Width;
Uri fileUri = new Uri(file.FullName);
// Create source
BitmapImage myBitmapImage = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit();
myBitmapImage.UriSource = fileUri;
// To save significant application memory, set the DecodePixelWidth or
// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = actualPixelWidth;
myBitmapImage.EndInit();
return myBitmapImage;
}
}
}
Then in your source code you do the following
private void zmenObrazek()
{
// do you need the first forward slash?
// (I assume "Content" is a folder in the bin directory)
obr_0_1.Source = Helper.CreateSource("Content/Obrazky/half-life.png");
}
Is the image above (half-life.png) found in the bin folder under Content/Obrazky?
If not you may also want to change the image property, Copy to Output Directory, to "Copy always" (when you add an image to project folder the default for this property is "Do not copy").

Related

Loaded pictureBox.ImageLocation is null

I'm trying to do something when I click image displayed inside pictureBox1.
pictureBox is loaded with this code:
string imgpath = #"img\256.png";
pictureBox48.Image = Image.FromFile(imgpath);
Then control is released to me so I can see that the picture loaded correctly.
Then i click the picture:
public void pictureBox48_Click(object sender, EventArgs e)
{
string variable1 = pictureBox48.ImageLocation;
Form3 fo = new Form3(variable1);
fo.ShowDialog();
}
This doesn't work. When I debug the code I see that variable1 stay null, that is pictureBox48.ImageLocation is null. Why is that? Shouldn't it be the path to the image that is assigned there?
You can't get the image path when you set the image using the Image property because you are assigning an Image object which can come from different sources.
Set the image using ImageLocation.
string imgpath = #"img\256.png";
pictureBox48.ImageLocation = imgpath;
When you click in the PictureBox you can get the path using the same property:
public void pictureBox48_Click(object sender, EventArgs e)
{
string variable1 = pictureBox48.ImageLocation;
Form3 fo = new Form3(variable1);
fo.ShowDialog();
}
When dealing with Image or PictureBox I would recommend to not use something like Location or Path of the image. Assume that when the image is loaded user removes it from the hard drive and you're left with the code full of errors.
That's why you should rely on Image itself as it contains every information about the image like pixel format, width, height and raw pixel data.
I would recommend you to just copy the image, not the path to the file.
This piece of code should give you a hint:
pixtureBox48.Image = Image.FromFile(imgPath);
// above code assumes that the image is still on hard drive and is accessible,
// now let's assume user deletes that file. You have the data but not on the physical location.
Image copyImage = (Image)pictureBox48.Image.Clone();
Form3 fo = new Form(copyImage); // change .ctor definition to Form(Image copy)
fo.ShowDialog();

Cannot delete file when used in DataContext

My application shows images on screen (images based upon files on the local computer) and users can delete them if needed.
Every time I try to delete a file it results in the following error message:
"The process cannot access the file 'C:\\Users\\Dave\\Desktop\\Duplicate\\Swim.JPG' because it is being used by another process."
I understand the error message.
I have a UserControl which accepts a file path (via a parameter in the constructor) and then binds it to it's (UserControl) DataContext.
As part of debugging this issue I have found the issue is due to setting the DataContext within the UserControl. If I remove this.DataContext = this; from within my UserControl then I can delete the file.
So, my TestUnit looks like
Ui.UserControls.ImageControl ic = new ImageControl(
#"C:\Users\Dave\Desktop\Duplicate\Swim.JPG");
try
{
File.Delete(#"C:\Users\Dave\Desktop\Duplicate\Swim.JPG");
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
The UserControl CodeBehind
public ImageControl(string path)
{
this.FilePath = path;
this.DataContext = this; // removing this line allows me to delete the file!
InitializeComponent();
}
#region Properties
private string _filePath;
public string FilePath
{
get { return _filePath; }
set
{
_filePath = value;
OnPropertyChanged("FilePath");
}
}
If it matters, my UserControl XAML is using the 'Image' control, bound to 'FilePath'
I have tried making the UserControl null before deleting, this did not help.
I have tried adding the IDisposible Interface to my UserControl and within the Dispose() method setting this.DataContext = null; but this did not help.
What am I doing wrong? How can I delete this file (or more accurately, make it unused).
The problem is not the DataContext, but simply the way WPF loads images from files.
When you bind the Source property of an Image control to a string that contains a file path, WPF internally creates a new BitmapFrame object from the path basically like this:
string path = ...
var bitmapImage = BitmapFrame.Create(new Uri(path));
Unfortunately this keeps the Image file opened by WPF, so that you can't delete it.
To get around this you have to change the type of your image property to ImageSource (or a derived type) and load the image manually like shown below.
public ImageSource ImageSource { get; set; } // omitted OnPropertyChanged for brevity
private ImageSource LoadImage(string path)
{
var bitmapImage = new BitmapImage();
using (var stream = new FileStream(path, FileMode.Open))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze(); // optional
}
return bitmapImage;
}
...
ImageSource = LoadImage(#"C:\Users\Dave\Desktop\Duplicate\Swim.JPG");

Adding a picture from a resource to a picture box

I got this issue with displaying a image that i allready have added as a resource. I am guessing i am missing something vital but i cant find what it is. I am hoping that someone has a better idea of what i am doing wrong atm.
I have added an .bmp image into the solutiontree and changed the build action properties of that image to Embedded resource but i cant figure out how to call that image from the pipe?
as the user clicks a button the image should be sent to the imagebox, the code i have written so far looks like this:
this is ofs only the button_click code:
private void button1_Click(object sender, EventArgs e)
{
//Show image in the picturebox of selected cake
Image image = Image.FromFile(fruitcake.jpg);
pictbox.Image = image;
pictbox.Height = 163;
pictbox.Width = 223;
choice = 1;
lblCookiesPerGram.Text = string.Empty;
}
Anyone has an idea of what i am doing wrong or can i do this in another war? mind thou its 4 buttons the user clicks and there is a image for each one ;)
//Regards
If you go to your Solution - Properties window and select the Resources tab and add the image through this manager, then the images can be directly referenced like this:
Image image = Properties.Resources.fruitcake;
To retrieve an image from a resource, you can do something like:
using (Stream imgStream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(
"MyNamespace.resources.fruitcake.jpg"))
{
var image = new Bitmap(imgStream);
pictBox.Image = image;
pictBox.Height = image.Height;
pictBox.Width = image.Width;
}

Validating WPF Bitmap Image Loaded from URI at Runtime

I am trying to load a BitmapImage at runtime from a URI. I use a default image in my XAML user control which I'd like to replace via databindings. This works.
The problem I'm having is in situations where an invalid file is used for the replacement image (maybe it's a bad URI, or maybe the URI specifies a non-image file). When this happens, I want to be able to check the BitmapImage object to see if it was correctly loaded. If not, I want to stick to the default image being used.
Here's the XAML:
<UserControl x:Class="MyUserControl">
<Grid>
<Image
x:Name="myIcon"
Source="Images/default.png" />
</Grid>
</UserControl>
And the relevant codebehind:
public static readonly DependencyProperty IconPathProperty =
DependencyProperty.Register(
"IconPath",
typeof(string),
typeof(MyUserControl),
new PropertyMetadata(null, new PropertyChangedCallback(OnIconPathChanged)));
public string IconPath
{
get { return (string)GetValue(IconPathProperty); }
set { SetValue(IconPathProperty, value); }
}
private static void OnIconPathChanged(
object sender,
DependencyPropertyChangedEventArgs e)
{
if (sender != null)
{
// Pass call through to the user control.
MyUserControl control = sender as MyUserControl;
if (control != null)
{
control.UpdateIcon();
}
}
}
public void UpdateIcon()
{
BitmapImage replacementImage = new BitmapImage();
replacementImage.BeginInit();
replacementImage.CacheOption = BitmapCacheOption.OnLoad;
// Setting the URI does not throw an exception if the URI is
// invalid or if the file at the target URI is not an image.
// The BitmapImage class does not seem to provide a mechanism
// for determining if it contains valid data.
replacementImage.UriSource = new Uri(IconPath, UriKind.RelativeOrAbsolute);
replacementImage.EndInit();
// I tried this null check, but it doesn't really work. The replacementImage
// object can have a non-null UriSource and still contain no actual image.
if (replacementImage.UriSource != null)
{
myIcon.Source = replacementImage;
}
}
And here's how I might create an instance of this user control in another XAML file:
<!--
My problem: What if example.png exists but is not a valid image file (or fails to load)?
-->
<MyUserControl IconPath="C:\\example.png" />
Or maybe someone can suggest a different/better way to go about loading an image at runtime. Thanks.
Well, BitmapImage class has two events, which will be raised when either download or decoding has failed.
yourBitmapImage.DownloadFailed += delegate { /* fall to your def image */ }
yourBitmapImage.DecodeFailed += delegate { /* fall to your def img */ }
On a side note, if you're trying to implement fallback placeholder: http://www.markermetro.com/2011/06/technical/mvvm-placeholder-images-for-failed-image-load-on-windows-phone-7-with-caliburn-micro/ seems nice.
It's crude, but I found that a non-valid BitmapImage will have width and height of 0.
BitmapImage image;
if(image.Width > 0 && image.Height > 0)
{
//valid image
}
You can try this check
if (bitmapImage.UriSource==null || bitmapImage.UriSource.ToString()).Equals(""))
{
Console.WriteLine("path null");
}
else
{
bitmapImage.EndInit();
}
This has already been answered. Please have a look at this and this. I think that both of them somewhat answer your question but I would prefer the former approach as it even checks for the contentType of the remote resource.
You can also have a look at this post.
Update:
In case of local files, this can be checked by simply creating an Image object using the Uri, or the path. If it is successful, it means the image is a valid image:
try
{
Image image = Image.FromFile(uri);
image.Dispose();
}
catch (Exception ex)
{
//Incorrect uri or filetype.
}

Loading Icons from a given path to display in WPF window

I have a tree that displays the directory and another panel that displays the files. Right now the files displayed have no icons. All i know is the path to the file. What i woudl like to do is get that files icon to display in that panel. I need the output to be and Image.source. Currently this is what i have
private ImageSource GetIcon(string filename)
{
System.Drawing.Icon extractedIcon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
ImageSource imgs;
using (System.Drawing.Icon i = System.Drawing.Icon.FromHandle(extractedIcon.ToBitmap().GetHicon()))
{
imgs = Imaging.CreateBitmapSourceFromHIcon(
i.Handle,
new Int32Rect(0, 0, 16, 16),
BitmapSizeOptions.FromEmptyOptions());
}
return imgs;
From there i call my itme and try to change its default icon with:
ImageSource i = GetIcon(f.fullname)
ic.image = i
ic is the given item to the list, f.fullname contains the path
here is the get and set of image
public BitmapImage Image
{
get { return (BitmapImage)img.Source; }
set { img.Source = value; }
}
It doesn't work and this is one of many ways I've tried it says it cant cast the different types. Does anyone have a way to do this?
I'm completely lost.
I'm assuming that img is a standard Image control.
Your Image property is of type BitmapImage, which is a specific kind of ImageSource. CreateBitmapSourceFromHIcon returns an instance of an internal class called InteropBitmap, which cannot be converted to BitmapImage, resulting in an error.
You need to change you property to ImageSource (or BitmapSource, which CreateBitmapSourceFromHIcon returns, and inherits ImageSource), like this:
public ImageSource Image
{
get { return img.Source; }
set { img.Source = value; }
}

Categories