I am trying to save and open a file which consists of a list of objects. My problem right now is that when I open the file I saved nothing happens. The program is supposed to use a dragTo event. When I use that event the object that is dragged gets saved in the list "ojl"
Here is my methods for Save and open.
DragTo dragto1 = new DragTo();
OpenFileDialog openDialog = new OpenFileDialog();
SaveFileDialog saveDialog = new SaveFileDialog();
BinaryFormatter form = new BinaryFormatter();
public void Save() // Method to save list of objects (Save)
{
saveDialog.Filter = "dat files (*.dat)|*.dat|All files (*.*)|*.*";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
FileStream outStr = new FileStream(saveDialog.FileName, FileMode.Create); //Create new FileStream
form.Serialize(outStr, dragto1.Ojl);
outStr.Close();
}
}
public void Open() // Method for open saved list of objects (Load/Open)
{
openDialog.Filter = "dat files (*.dat)|*.dat|All files (*.*)|*.*";
if (openDialog.ShowDialog() == DialogResult.OK)
{
FileStream inStr = new FileStream(openDialog.FileName, FileMode.Open); //Create new FileStream
dragto1.Ojl = (List<DrawnObject>)form.Deserialize(inStr);
inStr.Close();
}
and the list is in another class (DragTo)
private List<DrawnObject> ojl = new List<DrawnObject>();
public List<DrawnObject> Ojl
{
get { return ojl; }
set { ojl = value; }
}
I also refresh the controller which the objects are inside of. but the list hasn't got the new values in it from the open method. Does the format of the file have anything to do with it (.dat)?
Related
I have some code:
public static UIElementCollection DeSerializeXAML(string filename)
{
// Load XAML from file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
return System.Windows.Markup.XamlReader.Load(fs) as UIElementCollection; //EXCEPTION
}
}
// Serializes any UIElement object to XAML using a given filename.
public static void SerializeToXAML(UIElementCollection elements, string filename)
{
// Use XamlWriter object to serialize element
string strXAML = System.Windows.Markup.XamlWriter.Save(elements);
// Write XAML to file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Create(filename))
{
using (System.IO.StreamWriter streamwriter = new System.IO.StreamWriter(fs))
{
streamwriter.Write(strXAML);
}
}
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.FileName = "UIElement File"; // Default file name
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Save document
string filename = dlg.FileName;
SerializeToXAML(myCanvas.Children, filename);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
UIElementCollection elements = DeSerializeXAML(filename) as UIElementCollection;
// Add all child elements (lines, rectangles etc) to canvas
myCanvas.Children.Clear();
foreach (UIElement el in elements)
{
myCanvas.Children.Add(el);
}
}
}
That works fine with serialization but when you deserialize, an exception is thrown.
Text of exception(translated with google):"You did not find a suitable constructor for the type" System.Windows.Controls.UIElementCollection.
"You can use the Arguments or FactoryMethod directives to generate this type.": Line number "1" and position in line "22".
A UIElementCollection instance is tied to a specific Visual, and as such, it is unsuitable for serialization (as #kostya-k points out). The deserialization logic doesn't know how to create a new UIElementCollection because it doesn't know which Visual to associate it with. And creating a new collection is pointless anyway, as you are simply transferring the values to myCanvas.Children.
The good news is that you can use a XamlObjectWriter to populate myCanvas.Children directly instead of instantiatating a new collection:
public static void DeSerializeXAML(UIElementCollection elements, string filename)
{
var context = System.Windows.Markup.XamlReader.GetWpfSchemaContext();
var settings = new System.Xaml.XamlObjectWriterSettings
{
RootObjectInstance = elements
};
using (var reader = new System.Xaml.XamlXmlReader(filename))
using (var writer = new System.Xaml.XamlObjectWriter(context, settings))
{
System.Xaml.XamlServices.Transform(reader, writer);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
myCanvas.Children.Clear();
DeSerializeXAML(myCanvas.Children, filename);
}
}
UIElementCollection is not intended for serialization. It meant to be used when building a WPF visual tree.
I have a Windows Form program that you enter data in to, that data can be saved to a XML format file, I am giving it my own extention of .WSDA, I'd like to be able to without having the program loaded, click this file and have it run the same routine i use to save it.
Here are the events for saving and loading the files via button...
private void button11_Click(object sender, EventArgs e)
{
// Opens Dialog Box
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Workspace Data File |*.wsda";
saveFileDialog1.Title = "Save current Workspace data.";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
// Create an instance of the FormData class and populate it with form data..
FormData FormSave = new FormData();
FormSave.form_type = textForm.Text;
FormSave.policy_num = textPolicynum.Text;
FormSave.effective_date = textEffdate.Text;
FormSave.sai_number = textSAI.Text;
FormSave.office_code = textOffice.Text;
FormSave.change_date = textChgdate.Text;
FormSave.name_insured = textNamedIns.Text;
FormSave.error_code = textErrorCode.Text;
FormSave.producer_code = textProducer.Text;
FormSave.nticid = textNtic.Text;
FormSave.notes = textNotes.Text;
// Create and XmlSerializer to serialize the data.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
// XmlTextWriter writes file.
XmlTextWriter xtw = new XmlTextWriter(new StreamWriter(saveFileDialog1.FileName));
xs.Serialize(xtw, FormSave);
// Stop writing to file.
xtw.Flush();
xtw.Close();
}
}
private void button12_Click(object sender, EventArgs e)
{
// Opens Dialog Box
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Workspace Data File |*.wsda";
openFileDialog1.Title = "Save current Workspace data.";
openFileDialog1.ShowDialog();
if (openFileDialog1.FileName != "")
{
//XmlTextReader Reads file.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
XmlTextReader xtw = new XmlTextReader(openFileDialog1.FileName);
FormData FormLoad = new FormData();
//Converts it to form data again.
FormLoad = xs.Deserialize(xtw) as FormData;
//Updates the fields with the data file.
textForm.Text = FormLoad.form_type;
textPolicynum.Text = FormLoad.policy_num;
textEffdate.Text = FormLoad.effective_date;
textSAI.Text = FormLoad.sai_number;
textOffice.Text = FormLoad.office_code;
textProducer.Text = FormLoad.producer_code;
textChgdate.Text = FormLoad.change_date;
textNamedIns.Text = FormLoad.name_insured;
textErrorCode.Text = FormLoad.error_code;
textNtic.Text = FormLoad.nticid;
textNotes.Text = FormLoad.notes;
// Stop Reading File.
xtw.Close();
}
}
I found a work for what I needed to accomplish.
Program.cs I made with the following.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
if (args.Length == 1) //make sure an argument is passed
{
FileInfo file = new FileInfo(args[0]);
if (file.Exists) //make sure it's actually a file
{
File.Copy(file.FullName, "./workspace.tmp"); //copys the associated file to the program folder and renames it.
// This is importants since the name of the file can be anything *.wsda
}
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Then in the actual form I run a IF statement for a temp file to load which the program.cs handles, as you see its then copied to workspace.tmp
This parses the file and sets the form textbox values to that of the loaded file.
if (System.IO.File.Exists("./workspace.tmp"))
{
//XmlTextReader Reads file.
XmlSerializer xs = new XmlSerializer(typeof(FormData));
XmlTextReader xtw = new XmlTextReader("./workspace.tmp");
FormData FormLoad = new FormData();
//Converts it to form data again.
FormLoad = xs.Deserialize(xtw) as FormData;
//Updates the fields with the data file.
textForm.Text = FormLoad.form_type;
textPolicynum.Text = FormLoad.policy_num;
textEffdate.Text = FormLoad.effective_date;
textSAI.Text = FormLoad.sai_number;
textOffice.Text = FormLoad.office_code;
textProducer.Text = FormLoad.producer_code;
textChgdate.Text = FormLoad.change_date;
textNamedIns.Text = FormLoad.name_insured;
textErrorCode.Text = FormLoad.error_code;
textNtic.Text = FormLoad.nticid;
textNotes.Text = FormLoad.notes;
// Stop Reading File.
xtw.Close();
File.Delete("./workspace.tmp"); // since its done loading it, deletes the file.
}
I need to save a file using SaveFileDialog to a specific folder.
For example, say we want to save in "c:\MyNewFolder". If the folder doesn't exist, create it and save there, or only save there if the folder does exist.
String fileName="";
String date = DateTime.Now.Day+"-"+DateTime.Now.Month+"-"+DateTime.Now.Year;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.FileName = fileName;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
using (Stream s = File.Open(saveFileDialog1.FileName,FileMode.CreateNew))
using (StreamWriter sw = new StreamWriter(s))
{
sw.WriteLine(tbName.Text);
sw.WriteLine(tbSummary.Text);
}
}
You can look for
SaveFileDialog save = new SaveFileDialog();
save.InitialDirectory = "c:\\MyNewFolder";
save.RestoreDirectory = true;
string strPath="c:\MyNewFolder";
if (!Directory.Exists(strPath))
{
Directory.CreateDirectory(strPath);
}
else
{
//Continue your logic and append your file name
}
I am selecting file from openfiledialoge and displaying it in picturebox and its name in textbox when I click on delete button I am getting exception The process cannot access the file because it is being used by another process.
I searched a lot for this exception to get resolved but i didn't fine any of them working, when i tried closing file with imagename which is in textbox i.e the file i am displaying in picturebox ; using IsFileLocked method,this closes and deletes all files of particular directory path ,but how can I delete the only file shown in picturebox,where I am going wrong
public partial class RemoveAds : Form
{
OpenFileDialog ofd = null;
string path = #"C:\Users\Monika\Documents\Visual Studio 2010\Projects\OnlineExam\OnlineExam\Image\"; // this is the path that you are checking.
public RemoveAds()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (System.IO.Directory.Exists(path))
{
ofd = new OpenFileDialog();
ofd.InitialDirectory = path;
DialogResult dr = new DialogResult();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Image img = new Bitmap(ofd.FileName);
string imgName = ofd.SafeFileName;
txtImageName.Text = imgName;
pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
ofd.RestoreDirectory = true;
}
}
else
{
return;
}
}
private void button2_Click(object sender, EventArgs e)
{
//Image img = new Bitmap(ofd.FileName);
string imgName = ofd.SafeFileName;
if (Directory.Exists(path))
{
var directory = new DirectoryInfo(path);
foreach (FileInfo file in directory.GetFiles())
{ if(!IsFileLocked(file))
file.Delete();
}
}
}
public static Boolean IsFileLocked(FileInfo path)
{
FileStream stream = null;
try
{ //Don't change FileAccess to ReadWrite,
//because if a file is in readOnly, it fails.
stream = path.Open ( FileMode.Open, FileAccess.Read, FileShare.None );
}
catch (IOException)
{ //the file is unavailable because it is:
//still being written to or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
}
Thanks in advance for any help
The (previously) accepted answer to this question is very poor practice. If you read the documentation on System.Drawing.Bitmap, in particular for the overload that creates a bitmap from a file, you will find :
The file remains locked until the Bitmap is disposed.
in your code you create the bitmap and store it in a local variable but you never dispose of it when you are done. This means your image object has gone out of scope but has not released its lock on the image file you are trying to delete. For all objects that implement IDisposable (like Bitmap) you must dispose of them yourself. See this question for example (or search for others - this is a very important concept!).
To correct the problem properly you simply need to dispose of the image when you are done with it :
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Image img = new Bitmap(ofd.FileName); // create the bitmap
string imgName = ofd.SafeFileName;
txtImageName.Text = imgName;
pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
ofd.RestoreDirectory = true;
img.Dispose(); // dispose the bitmap object
}
Please do not take the advice in the answer below - you should nearly never need to call GC.Collect and if you need to do it to make things work it should be a very strong signal that you are doing something else wrong.
Also, if you only want to delete the one file (the bitmap you have displayed) your deletion code is wrong and will delete every file in the directory as well (this is just repeating Adel's point). Further, rather than keep a global OpenFileDialog object alive simply to store the file name, I would suggest getting rid of that and saving just the file info :
FileInfo imageFileinfo; //add this
//OpenFileDialog ofd = null; Get rid of this
private void button1_Click(object sender, EventArgs e)
{
if (System.IO.Directory.Exists(path))
{
OpenFileDialog ofd = new OpenFileDialog(); //make ofd local
ofd.InitialDirectory = path;
DialogResult dr = new DialogResult();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Image img = new Bitmap(ofd.FileName);
imageFileinfo = new FileInfo(ofd.FileName); // save the file name
string imgName = ofd.SafeFileName;
txtImageName.Text = imgName;
pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
ofd.RestoreDirectory = true;
img.Dispose();
}
ofd.Dispose(); //don't forget to dispose it!
}
else
{
return;
}
}
Then in your second button handler you can just delete the one file you are interested in.
private void button2_Click(object sender, EventArgs e)
{
if (!IsFileLocked(imageFileinfo))
{
imageFileinfo.Delete();
}
}
I had the same problem : I loaded a file in a PictureBox and when trying to delete it I got the same exception.
This occurred only when the image was displayed.
I tried them all :
picSelectedPicture.Image.Dispose();
picSelectedPicture.Image = null;
picSelectedPicture.ImageLocation = null;
and still got the same exception.
Then I found this on CodeProject : [c#] delete image which is opened in picturebox.
Instead of using PictureBox.Load() it creates an Image from the file and sets it as PictureBox.Image:
...
// Create image from file and display it in the PictureBox
Image image = GetCopyImage(imagePath);
picSelectedPicture.Image = image;
...
private Image GetCopyImage(string path) {
using (Image image = Image.FromFile(path)) {
Bitmap bitmap = new Bitmap(image);
return bitmap;
}
}
No more exceptions when I delete the file.
IMHO, this is the most suitable solution.
EDIT
I forgot to mention that you can safely delete the file immediately after display :
...
// Create image from file and display it in the PictureBox
Image image = GetCopyImage(imagePath);
picSelectedPicture.Image = image;
System.IO.File.Delete(imagePath);
...
use this code
string imgName = ofd.SafeFileName;
if (Directory.Exists(path))
{
var directory = new DirectoryInfo(path);
foreach (FileInfo file in directory.GetFiles())
{
GC.Collect();
GC.WaitForPendingFinalizers();
file.Delete();
}
}
Your button2_Click event handler is cycling through all the files inside your directory & doing the deletes.
You need to change your code like the following:
public partial class RemoveAds : Form
{
OpenFileDialog ofd = null;
string path = #"C:\Users\Monika\Documents\Visual Studio 2010\Projects\OnlineExam\OnlineExam\Image\"; // this is the path that you are checking.
string fullFilePath;
public RemoveAds()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (System.IO.Directory.Exists(path))
{
ofd = new OpenFileDialog();
ofd.InitialDirectory = path;
DialogResult dr = new DialogResult();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Image img = new Bitmap(ofd.FileName);
string imgName = ofd.SafeFileName;
txtImageName.Text = imgName;
pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
fullFilePath = ofd.FilePath;
ofd.RestoreDirectory = true;
}
}
else
{
return;
}
}
private void button2_Click(object sender, EventArgs e)
{
FileInfo file = new FileInfo(fullFilePath);
if(!IsFileLocked(file))
file.Delete();
}
}
public static Boolean IsFileLocked(FileInfo path)
{
FileStream stream = null;
try
{ //Don't change FileAccess to ReadWrite,
//because if a file is in readOnly, it fails.
stream = path.Open ( FileMode.Open, FileAccess.Read, FileShare.None );
}
catch (IOException)
{ //the file is unavailable because it is:
//still being written to or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
}
By using GetThumnailImage you have to specify the width and height which is static.
Use the Load method instead.
eg: pictureBox1.Load(Path to the image); by using this u will have no problem in deleting the image or the folder before closing the app. no other methods need to be created.
hope this helps
I have a "save" button so when users click, it will do a saving of xml file(xml serialization). A savefiledialog is used here and when i press cancel without selecting any file an "Argument Exception" occurs and says "Empty path name is not legal". How do i handle this exception? I would like the form to remain the same even without any path selected in the savefiledialog. Many thanks.
My savefiledialog snippet:
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
string savepath;
SaveFileDialog DialogSave = new SaveFileDialog();
// Default file extension
DialogSave.DefaultExt = "txt";
// Available file extensions
DialogSave.Filter = "XML file (*.xml)|*.xml|All files (*.*)|*.*";
// Adds a extension if the user does not
DialogSave.AddExtension = true;
// Restores the selected directory, next time
DialogSave.RestoreDirectory = true;
// Dialog title
DialogSave.Title = "Where do you want to save the file?";
// Startup directory
DialogSave.InitialDirectory = #"C:/";
DialogSave.ShowDialog();
savepath = DialogSave.FileName;
DialogSave.Dispose();
DialogSave = null;
...
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, formsaving);
}
}
My argument exception occurs at this line:
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, formsaving);
}
The problem here is that you do not care about the result of the Save dialog, and you try to save even if the user clicked Cancel. You should change the code to look something like this instead:
...
DialogSave.InitialDirectory = #"C:/";
if( DialogSave.ShowDialog() == DialogResult.OK )
{
savepath = DialogSave.FileName;
DialogSave = null;
...
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, formsaving);
}
}
DialogSave.Dispose();
You probably don't want to save if the user cancels the dialog? Check for the result from ShowDialog and act accordingly:
if (DialogSave.ShowDialog() == true)
{
savepath = DialogSave.FileName;
...
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, formsaving);
}
}