I was trying to delete an Image from the view Model after some modification but I'm getting this error message IOException was unhandled
I disposed the current bitmap currImgHandler.CurrentBitmap.Dispose();and also made the Image Source to be null ViewedPhoto.Source = null;
if i click on the button which has the Rotate function (90°) once and clikcing on the delete function which produces the error IOException was unhandled
If i clcik on the button Roate function twicethen click on Delete function; I don't get any error and it deletes image without any problem.
What is the mistake am I doing here? Thank you
Selecting an Image from ListView:
private string saveFilname;
private void showImage(object sender, SelectionChangedEventArgs args)
{
ListBox list = ((ListBox)sender);
if (list != null)
{
int index = list.SelectedIndex;
if (index >= 0)
{
ImageFileViewModel image = imageListBox.SelectedItem as ImageFileViewModel;
if ((image != null))
{
saveFilname = image.FileName.ToString();
currImgHandler.CurrentFileHandler.Load(image.FileName);
PaintImage();
}
}
}
}
Delete Function:
private void bDeletePhoto_Click(object sender, RoutedEventArgs e)
{
ImageFileCollectionViewModel viewModel = imageListBox.DataContext as ImageFileCollectionViewModel;
if (viewModel != null)
{
ImageFileViewModel image = imageListBox.SelectedItem as ImageFileViewModel;
if (image != null)
{
//remove physical file from disk:
currImgHandler.CurrentBitmap.Dispose();
ViewedPhoto.Source = null;
File.Delete(image.FileName);
//remove item from ObservableCollection:
viewModel.AllImages.Remove(image);
}
}
}
//Rotate Function:
private void Button_Click(object sender, RoutedEventArgs e)//Rotate
{
currImgHandler.CurrentRotationHandler.Flip(RotateFlipType.Rotate90FlipNone);
PaintImage();
}
private void PaintImage()
{
System.IO.MemoryStream stream = new System.IO.MemoryStream();
currImgHandler.CurrentBitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
stream.Position = 0;
byte[] data = new byte[stream.Length];
stream.Read(data, 0, Convert.ToInt32(stream.Length));
BitmapImage bmapImage = new BitmapImage();
bmapImage.BeginInit();
bmapImage.CacheOption = BitmapCacheOption.OnLoad;
bmapImage.StreamSource = stream;
bmapImage.EndInit();
ViewedPhoto.Source = bmapImage; //ImageBox
ViewedPhoto.Stretch = Stretch.Uniform;
}
Error message:
Your application is throwing an IOException. Likely culprit:
File.Delete(image.FileName);
IMO You should avoid making calls like this directly in event handlers for the reason demonstrated here - it is hard to catch exceptions thrown directly from an event handler.
If implementing MVVM this doesn't tend to occur.
Perhaps the account privileges under which your application is running are not sufficient to let you delete the file. Please check the credentials of this account against operations on the file you want to delete.
It's only a supposition though, it's hard to be sure without the IOEXception content, and it could also be because the path you're using doesn't exist, etc...
After Drew Rsuggestion i have added a method in the MVVM itself:
public void RemoveOldPhotoItem(ImageFileViewModel imageFile)
{
this._allImages.Remove(imageFile);
this.DataItemsCount++;
File.Delete(imageFile.FileName);
}
I need to dispose the image which was used by a 3rd party .dll....which i disposed properly.
Sorry guys it was my mistake. Thank you for your support!
Related
Part of my application will hopefully be able to hash files which the user specifies, but I am stuck on the actual code itself. Note that:
filepath512(.text) = Textbox in which the user inserts the file path
fileout(.text) = Output textbox
button21_click = "Hash/confirm" button used to start the hashing algorithm
When I run the application and run the hashing algorithm, nothing happens (the result does not appear in the Output textbox).
A few weeks ago, I actually successfully executed the hashing algorithm with the identical code (well, same structure) and it worked perfectly well!
I have just begun working with C#, so please excuse any messy code!
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string filePath = e.Argument.ToString();
byte[] buffer;
int bytesRead;
long size;
long totalBytesRead = 0;
using (Stream file = File.OpenRead(filePath))
{
size = file.Length;
using (HashAlgorithm hasher = SHA512.Create())
{
do
{
buffer = new byte[4096];
bytesRead = file.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
backgroundWorker1.ReportProgress((int)((double)totalBytesRead / size * 100));
}
while (bytesRead != 0);
hasher.TransformFinalBlock(buffer, 0, 0);
e.Result = MakeHashString(hasher.Hash);
}
}
}
private static string MakeHashString(byte[] hashbytes)
{
StringBuilder hash = new StringBuilder(32);
foreach (byte b in hashbytes)
hash.Append(b.ToString("X2").ToLower());
return hash.ToString();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar3.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
fileout512.Text = e.Result.ToString();
progressBar3.Value = 0;
}
private void button21_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync(filepath512.Text);
}
Actually, your code misses a lot of sanity checks. First of all, you should use OpenFileDialog instead of a direct user input for specifying a path. Second, once the process starts, you should make sure the file exists using File.Exists method... if it doesn't, you should return an appropriate result.
Probably, an exception is being thrown by your code, somewhere. From the official MSDN documentation:
If the operation completes successfully and its result is assigned in
the DoWork event handler, you can access the result through the
RunWorkerCompletedEventArgs.Result property.
[...]
Your RunWorkerCompleted event handler should always check the Error
and Cancelled properties before accessing the Result property. If an
exception was raised or if the operation was canceled, accessing the
Result property raises an exception.
So check error details using the Error properties of the event arguments in order to make sure that your code was properly executed without exceptions. If this is the case, you must fix the code so that the hashing doesn't fail anymore.
does the file exists? you have to check whether the file exists always before trying to do operations. debug the filepath and see whether it exist, and it has read permissions.
I am trying to write a practice Drag and Drop program.
This program will display a picture (JPG or PNG or Bitmap) when one is dropped on it. It will play a music file when dropped on it and it will play a video when a video file is dropped on it.
I would like the drop Icon to indicate what kind of file is about to be dropped when the DragOver event is fired. And if the file type is not compatible with my program I want the Icon to be able to indicate that as well.
I have been going through the DragEventArgs class for weeks trying to figure out a way of being able to tell the difference between the 3 types of media file but I have come up empty. Can anyone help with this?
You can use the DragUIOverride to customize the look of the dragged object.
You can set it with the DragOver event on the target element:
private async void Grid_DragOver(object sender, DragEventArgs e)
{
e.DragUIOverride.Caption = "Some caption";
e.DragUIOverride.IsCaptionVisible = true;
e.DragUIOverride.IsContentVisible = true;
e.DragUIOverride.IsGlyphVisible = true;
e.AcceptedOperation = DataPackageOperation.Copy;
//check the type of the file
var items = await e.DataView.GetStorageItemsAsync();
if (items.Any())
{
var storageFile = items[0] as StorageFile;
if ( storageFile.FileType == ".jpg" )
{
e.DragUIOverride.SetContentFromBitmapImage(
new BitmapImage(new Uri("ms-appx:///Assets/jpgIcon.png")));
}
else if ( storageFile.FileType == "png" )
{
e.DragUIOverride.SetContentFromBitmapImage(
new BitmapImage(new Uri("ms-appx:///Assets/pngIcon.png")));
}
//...
else
{
//for disallowed file types
e.AcceptedOperation = DataPackageOperation.None;
e.DragUIOverride.SetContentFromBitmapImage(
new BitmapImage(new Uri("ms-appx:///Assets/errorIcon.png")));
}
}
}
I'm making a simple Windows Phone 8.1 Silverlight app. The idea is that I can make an entry with a picture (taken with the camera) and add a title and description text to it. Once an entry is saved, a button appears on the main page to view it. So I made 3 entries and they are listed on the main page, but after navigating to their pages a few times, I get a NavigationFailed along with OutOfMemoryException. The pages are simple, they only contain 1 image along with some textblocks.
I thought the issue is that the images are still in memory, that's why I try to set them to null and force the garbage collector, but that didn't help at all. What could cause the OutOfMemory-exception?
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string id= "";
if (NavigationContext.QueryString.TryGetValue("id", out id))
{
foreach (cEntry entry in helper.entries)
{
if (entry.id.ToString() == id)
{
textBlock_viewText.Text = entry.text;
textBlock_viewTitle.Text = entry.title;
using (IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForApplication())
{
if (userStore.FileExists(entry.imageFileName))
{
using (IsolatedStorageFileStream imgStream = userStore.OpenFile(entry.imageFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(imgStream);
image_viewEntryImage.Source = bmp;
bmp = null;
}
}
}
}
}
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
image_viewEntryImage.Source = null;
GC.Collect();
}
You may need to freeze the BitmapImage.
As described here there is an issue with WPF (the typical framework for Windows Phone development) where BitmapImages can be incorrectly kept alive. While it was supposedly fixed a while back, people have reported still seeing the problem in some cases.
Instead of setting bmp as null try this.
public static void DisposeImage(BitmapImage image)
{
Uri uri= new Uri("oneXone.png", UriKind.Relative);
StreamResourceInfo sr=Application.GetResourceStream(uri);
try
{
using (Stream stream=sr.Stream)
{
image.DecodePixelWidth=1; //This is essential!
image.SetSource(stream);
}
}
catch { }
}
call this method and set source as this custom method after that assing bmp as null.
The GC not able to clear the memory. details are here Why do I get an OutOfMemoryException when I have images in my ListBox?
I have a smal application that should set a image to red or green depending on some tests that are made. The test can take a few second, and each one has a custom control with an image connected to it. When I click start I would like for the first test to be done, show the result by changing the image on that one, and then move on. But as it is now, all tests are made (maybe 10 seconds), then ALL the lights are changing at the same time. How can I force the custom control to update the image during the excecution?
private void start_Click(object sender, RoutedEventArgs e)
{
foreach (TestObject tObj in tObjList)
{
bool testResult = tObj.makeTest();
foreach (TestShower ts in m_TSList)
{
if (tObj == ts.gettObj())
{
if (testResult == true)
ts.setLightOn();
else
ts.setLightOff();
ts.UpdateLayout();
break;
}
}
}
}
public void setLightOn()
{
string strUri2 = String.Format(#"pack://application:,,,/;component/Images/Signal_On.png");
BitmapImage img = new BitmapImage(new Uri(strUri2));
iStatus.Source = null;
iStatus.Source = img;
}
public void setLightOff()
{
string strUri2 = String.Format(#"pack://application:,,,/;component/Images/Signal_Off.png");
BitmapImage img = new BitmapImage(new Uri(strUri2));
iStatus.Source = null;
iStatus.Source = img;
}
you should read into Async and await and perform each test at the same time and await the results (obviously this assumes your tests are not interdependant)
and some form of implementation of
Task.Factory.StartNew(() => {
var result = ts.makeTest();
setLight1(result);
})
Although without knowing more it would seem as though you could perform this using databinding to a ViewModel that implements INotifyPropertyChanged on a List of Test Objects.
but not performing the tests asynchronously is the main cause of your issue
i know external links are not really preferred in SO but here is a tutorial
http://www.youtube.com/watch?v=ZyFL3hjHADs
Run the tests in the background and then use Dispatcher to update UI thread:
For WPF & Net 4.5. you can use TPL
private void start_Click(object sender, RoutedEventArgs e)
{
Task.Run(()=>{
foreach (TestObject tObj in tObjList)
{
bool testResult = tObj.makeTest();
Dispatcher.Invoke(()=>{
foreach (TestShower ts in m_TSList)
{
if (tObj == ts.gettObj())
{
if (testResult == true)
ts.setLightOn();
else
ts.setLightOff();
ts.UpdateLayout();
break;
}
}});
}
}
});
}
i searched for embedding custom drag and drop cursor in my wpf app. i ended up with an article which i have no idea of ONE LINE in the code suggested in (it is highlighted with the comments):
private void textBlock2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock btn = (TextBlock)sender;
GiveFeedbackEventHandler handler = new GiveFeedbackEventHandler(DragSource_GiveFeedback);
btn.GiveFeedback += handler;
DataObject dataObj = new DataObject(btn.Text);
DragDrop.DoDragDrop(btn, dataObj, DragDropEffects.Move);
btn.GiveFeedback -= handler;
}
void DragSource_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
try
{
if (_allOpsCursor == null)
{
////////////////////////////////////////THE UNKOWN ONE LINE STARTS HERE
using (Stream cursorStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("SimplestDragDrop.DDIcon.cur")) // AND ENDS HERE
{
_allOpsCursor = new Cursor(cursorStream);
}
}
Mouse.SetCursor(_allOpsCursor);
e.UseDefaultCursors = false;
e.Handled = true;
}
finally { }
}
i checked GetManifestResourceStream, but i still have no idea what a mainfest resource is how could it be handled and where to start to get this caching idea (mentioned in the main article) to work.
Your assembly is loaded into memory as part of the AppDomain executing under the CLR. Because of this, if the resource is embedded into the assembly as part of the compilation process, using a stream to read an in-memory byte array is faster than having to go to disk to open a file, read its contents, close the file.
Alternatives are to store a byte array representing the resource within the source code, though more or less you're arriving at the same place using GetManifestResourceStream.