Image Control in Wpf showing previous image which was deleted - c#

I have an image control which is showing the preview image. If the user delete the image (which resides in folder) it should show the newly taken image.
but the image control shows the deleted image instead of showing new image.
// clear the image source before deleting the image.
// save image in the directory
public string globalFilePath;
int imageCount = Directory.GetFiles(imgDir, "*", SearchOption.TopDirectoryOnly).Length;
string filePath = Path.Combine(imgDir, "IMAGE_" + ++imageCount + ".jpeg");
globalFilePath = filePath;
// setting image control source
var strUri = new Uri(WebCamControl.globalFilePath, UriKind.Relative);
previewImage.Source = BitmapFromUri(strUri);
//Method
public static ImageSource BitmapFromUri(Uri source)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = source;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
return bitmap;
}
// delete image
previewImage.Source = null;
if (System.IO.File.Exists(WebCamControl.globalFilePath))
{
System.IO.File.Delete(WebCamControl.globalFilePath);
}
else
{
MessageBox.Show("File Not Exists");
}
After deleting the image in the directory file the image image control should show the new image, but my Image control shows the deleted image. please give me the solution.

In WPF, we generally don't need to use actual BitMapImage objects to display an Image. It's far easier to let the .NET Framework convert our string file paths to the images to the actual Image elements.
Also, it is far better to data bind the Image.Source to a property that implements the INotifyPropertyChanged interface (or a DepenedencyProperty):
<Image Source="{Binding YourImageFilePath}" ... />
Then, whenever a file path of a new image is set to the YourImageFilePath property, your displayed image will update immediately.
YourImageFilePath = filePath;

Try This one:
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.SetValue(System.Windows.Controls.Image.SourceProperty, null);
File.Delete(path);
OR
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.Source = null;
File.Delete(path)

Related

How to refresh a GridView content?

I have a GridView in my app that basically contains images as following:
<GridView x:Name="ImageGridView">
<Image x:Name="Image_1"/>
<Image x:Name="Image_2"/>
<Image x:Name="Image_3"/>
</GridView>
with this in codebehind for the images to Load:
public void SetImages()
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_1.png"));
Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_2.png"));
Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_3.png"));
}
The GridView shows the images just fine. However, I also have a Class that changes the colors of those Pictures based on existing values as fallowing:
This means that the Images sources don't change, and the paths to those images also remain as it is. The only thing changing are the colors in those images as demonstrated in the pictures.
However, when the colors-changing task is finished and the images are updated in the App's LocalState folder, they are not updated in the GridView images.
I have also tried creating an observable collection with the images in question. Binded the GridView to this collection, and at each color update I would include this:
GridView.ItemsSource = null;
GridView.ItemsSource = ImagesCollection;
It would work by changing some Images but not others. this happens randomly. If there it a way to await the first before executing the second, this might work out!
The question is: how to I ask the GridView to reload its content? Update its content? clear cache and re-fetch the Images?
Put this code into a method:
public void SetImages()
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Image_1.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_1.png"));
Image_2.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_2.png"));
Image_3.Source= new BitmapImage(new Uri(localFolder.Path + "/Image_3.png"));
}
Call this method once at the beginning and when you modified the images.
Don't be afraid to use MVVM. In your xaml bind the image sources to properties in your viewmodel.
XAML:
<GridView>
<Image Source="{Binding ImageSource1}"/>
<Image Source="{Binding ImageSource2}"/>
</GridView>
ViewModel:
public string ImageSource1 => Windows.Storage.ApplicationData.Current.LocalFolder + "/Image_1.png";
public string ImageSource2 => Windows.Storage.ApplicationData.Current.LocalFolder + "/Image_2.png";
// invoke the NotifyPropertyChanged event to enforce an update.
public void UpdateImages() {
InvokePropertyChanged(nameof(ImageSource1));
InvokePropertyChanged(nameof(ImageSource2));
}
Well I found an indirect dirty way to do it. to update the images in the GridView.
I started with clearing the ObservableCollection that the GridView binded to:
ThumnailsCollection.Clear();
Navigate to the folder where the thumbnails are saved to. each type of thumbnails are grouped in one folder. each time the color is changed where the thumbnails for it does not exist, new ones are generated. otherwise, it recalls the ones already on hand:
StorageFolder localFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
//Check if the main folder where the images are saved exist
IStorageItem storageItem = await localFolder.TryGetItemAsync("Thumnails");
if (storageItem != null)
{
//If it does, look into the subfolders. each image group of the same
//type and different colors are saved to tier own folder
StorageFolder ImagesFolder =
await localFolder.GetFolderAsync("Thumnails");
var queryOption =
new QueryOptions { FolderDepth = FolderDepth.Deep };
var flatWallpaperSubFolders =
await ImagesFolder .CreateFolderQueryWithOptions(queryOption).GetFoldersAsync();
foreach (StorageFolder subFolder in subFolders)
{
IStorageItem thumnail =
await subFolder.TryGetItemAsync($"{AlphaColorID} - {BetaColorID}.png");
if (thumnail != null)
{
//in each of the folders, look if the needed image
//exist or not
//If it does, add it to the ObservableCollection
BitmapImage icon =
new BitmapImage(new Uri(subFolder.Path + $"/{AlphaColorID} - {BetaColorID}.png"));
ThumnailsCollection.Add(new ThumnailsBitmap(icon));
}
else
{
//If the Image with the requested colors does not exist
//Render a new image with the needed colors
//the rendered image is added to the same subfolder with the other
// similar images
await ApplyColor(new Uri($"ms-appx:///Images/{subFolder.Name}-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", $"{subFolder.Name}");
BitmapImage icon =
new BitmapImage(new Uri(flatWallpaperSubFolder.Path + $"/{AlphaColor} - {BetaColor}.png"));
ThumnailsCollection.Add(new ThumnailsBitmap(icon));
}
}
}
else
{
//when run for the first time, all folders and images are missing
//through ApplyColor task, all Images are rendered and folders created
await ApplyColor(new Uri("ms-appx:///Images/Number-1-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", "Number-1");
await ApplyColor(new Uri("ms-appx:///ModernWallpaperGrayscale/Number-2-Thumnail.png"), $"{AlphaColor} - {BetaColor}.png", "Number-2");
//All needed to do is to all of those Images to the
//ObservableCollection
StorageFolder ImagesFolder = await localFolder.GetFolderAsync("Thumnails");
var queryOption =
new QueryOptions { FolderDepth = FolderDepth.Deep };
var flatWallpaperSubFolders =
await ImagesFolder.CreateFolderQueryWithOptions(queryOption).GetFoldersAsync();
foreach (StorageFolder subFolder in subFolders)
{
BitmapImage icon =
new BitmapImage(new Uri(subFolder.Path + $"/{AlphaColor} - {BetaColor}.png"));
ThumnailsCollection.Add(new ThumnailsBitmap(icon));
}
}

How to show an image obtained from a scanner using WIA in a picture box

I want to display an image retrieved from a scanner in a picturebox. So far I have been able to do it saving the image to a temporary file:
private void btnScan_Click(object sender, EventArgs e)
{
var fn = System.IO.Path.GetTempFileName();
System.IO.File.Delete(fn);
var image = Scanner.Scan();
image.SaveFile(fn);
_ScannedImage = Bitmap.FromFile(fn);
pictureBoxMain.Image = _ScannedImage;
}
Is there a way to convert the image data in the ImageFile class avoiding to save it to disk?
As per #C. Colin comment, theres' a way to get the bitbitmap from the ImageFile using a memory stream:
var imageBytes = (byte[])image.FileData.get_BinaryData();
var ms = new MemoryStream(imageBytes);
var img = Image.FromStream(ms);
Load a picturebox from a WIA ImageFile?
You can convert the ImageFile to Image, and after that create a Bitmap object:
var myImage = (Image)imageFile;
Bitmap bmp = new Bitmap(myImage);
Therefore you don't have to save (as you requested) in path.
Please tell me if this works for you.
See this post about converting from ImageFile to Image:
Load a picturebox from a WIA ImageFile?

How to set button backgroundimage in c#?

I'm new in this field. I'm working in windows application, I create panel and adding the buttons inside the panel. i want to retrieve the image from database and set to the background image in button.
This is my code,
FileName = objDR["Photopath"].ToString();
byte[] data = Encoding.UTF8.GetBytes(FileName);
MemoryStream ms = new MemoryStream(data);
image = new System.Drawing.Bitmap(ms);
Buttons[i].BackgroundImage = image;
initially put BackgroundImage property ON
OR
You can Code :
button1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.Image));

Detecting which image is used in an imagebox

I'm trying too make a memory game.
In this game when a button is klicked the button and an picturebox will be send into a List.
I want too use the images inside the pictureboxes as a way too use this code. But even when the two images are the same the code wont work. Is there a way too check the image used like Name.jpg.
if(buttonCount == 2)
{
if(pictureList[0].Image == pictureList[1].Image)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}
You could save an Id of the image (or e.g. the filename like you suggested) in the Tag.
So when loading the image into the picture box:
string path = "PATH";
pictureBox.Image = Image.FromFile(path);
pictureBox.Tag = path;
Then you could compare the Tag.
BUT I think (show us how you load the images please) this is not working as it is, because you load the image twice from the disk like:
pictureBox1.Image = Image.FromFile(path);
pictureBox2.Image = Image.FromFile(path);
Because then you have differen instances and so the equals returns false.
If you do it like the following it should also work:
var image = Image.FromFile(path);
pictureBox1.Image = image;
pictureBox2.Image = image;
In your current application, you do not have enough information associated with the image object to identify it. As such, you need to possibly extend the Image class to include this information or store it in some other way for comparison.
Extending Image class
public class GameImage : Image
{
public static GameImage GetImage(string filename)
{
GameImage img = (GameImage)Image.FromFile(filename);
img.FileName = filename;
return img;
}
public string FileName { get; private set; }
}
Then the comparison becomes
if(buttonCount == 2)
{
if(((GameImage)pictureList[0].Image).FileName == ((GameImage)pictureList[1].Image).FileName)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}
Note: Note tested!

updating an image in an image control

im trying to update an image in an image control that is bound to a class which implements INotifyPropertyChanged. i've tried most of the methods which relate to refreshing bitmap cache so that the image can refresh but none seems to work for my case. the image contorl is defined in the xaml file as: <Image Source="{Binding Chart}" Margin="0 0 0 0"/>
and in the code behind the class is:
private ImageSource imagechart = null;
public ImageSource Chart
{
get
{
return imagechart;
}
set
{
if (value != imagechart)
{
imagechart = value;
NotifyPropertyChanged("Chart");
}
}
}
after an event i now set the image using the following code:
c.Chart = image;
when i now run my application this will display the image but during the running of the application i update the image but calling this c.Chart = image; displays the initial image. i came to understand that WPF caches the image but all methods claiming to solve this dint work for me. one of the solutions that did not work for me is Problems overwriting (re-saving) image when it was set as image source
Try to change the return Type of your Image property to Uri. The TypeConverter on the Source Property should do the rest. If this doesnt work, verify that the resource has actually changed.
You can read the resource from your assembly using Assembly.GetManifestResourceStreams and resolve the bytes. Than manually save them with File.WriteAllBytes to your output directory an see if it has the expected image.
As far as i know Application Ressources (which are embedded into the assembly) can not be changed during runtime (?). You are referencing the assembly ressource and not an output ressource with your pack uri.
thank you all for your input coz through them i finally figure a way around this. so my xaml still remains bound as <Image Source="{Binding Chart}" Margin="0 0 0 0"/> but in the code behind i changed the class property chart to return a bitmap as shown below:
private BitmapImage image = null;
public BitmapImage Chart
{
get
{
return image;
}
set
{
if (value != image)
{
image = value;
NotifyPropertyChanged("Chart");
}
}
}
this class mind you implements INotifyPropertyChanged . at the point where i set the image i am now using this code:
BitmapImage img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
//in the following code path is a string where i have defined the path to file
img.UriSource = new Uri(string.Format("file://{0}",path));
img.EndInit();
c.Chart = img;
this works well for me and refreshes the image upon update.

Categories

Resources