I've created *.txt file with data like this:
deviceid,model,availability,renterID,renterName,reneterSurname,OS
0001,iPhone_5S,false,002,John,Dowland,iOS-7.1.2
0002,GalaxyS3,false,002,Amadeus,Mozart,Android-4.3.2
In my C# app (WPF application) got this function to operate on the file:
private void rentSaveButton_Click(object sender, RoutedEventArgs e)
{
StreamWriter sw = new StreamWriter(#"D:\deviceLib.txt", true);
var currentUser = _list.Where(u => u.Id == int.Parse(userIDTextBox.Text)).FirstOrDefault();
var currentDevice = _list2.Where(i => i.deviceId == int.Parse(deviceIDTextBox.Text)).FirstOrDefault();
if (currentDevice != null && currentUser != null)
{
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
sw.WriteLine();
sw.Close();
MessageBox.Show("Rent done. Thanks!");
tabControl.SelectedItem = mainTab;
}
else
{
MessageBox.Show("We don't have such device. Sorry :( ");
userIDTextBox.Clear();
deviceIDTextBox.Clear();
}
}
Now, the problem is that I can normally work on this file during program work, it changes values, can read it etc but when I turn off app (by X button) nothing happen. TXT file is untouched nor any changes are saved.
You aren't writing anything to the file.
sw.WriteLine(); // you need to pass a string in to this function
It seems to me that you must have invented a theory that any changes you make to currentDevice should, somehow, affect what's written to sw. What you're seeing here is what Karl Popper used to call "disconfirmation": Your theory predicts behavior that can be observed; you observe; the behavior is not happening. The first explanation for that is that your theory is wrong.
And that is in fact the correct explanation for what you're (not) seeing. There is absolutely no connection whatsoever between currentDevice and sw. None. It's like you're pressing buttons on the microwave in an effort to start your car. You'll be walking to work if you don't switch to another approach.
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
sw.WriteLine();
sw.Close();
All you do there is change a bunch of properties on a random object, refresh your data grid, and then write a newline, a newline and nothing else, to the output stream. Why does sw.WriteLine();, with no arguments do that? Well, it does that because that's what the designers decided it would do. There's nothing else it sanely can do, because you're not giving it anything to write. And that behavior is documented, which you would know if you had spent ten seconds reading the documentation.
If you want to write a non-empty line to a file, use one of the many, many overloads of WriteLine which are documented in the documentation. If you want to write just part of a line, use one of the many overloads of Write, which are also documented.
Something like this would be fine (I'm guessing at your field names; if you don't know what they are, maybe somebody else on StackOverflow knows what that part of your code looks like and can help you):
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
// Write fields in desired order of appearance in the file.
sw.Write(currentDevice.deviceID);
// There are many far superior ways to write a comma to the file,
// and I'll hear about all of them in comments, but we're keeping
// it as simple as possible for the moment.
sw.Write(",");
sw.Write(currentDevice.model);
sw.Write(",");
// Properties you just set
sw.Write(currentDevice.Availability);
sw.Write(",");
sw.Write(currentDevice.rentID);
sw.Write(",");
sw.Write(currentDevice.rentName);
sw.Write(",");
sw.Write(currentDevice.rentSurname);
sw.Write(",");
sw.Write(currentDevice.OS);
// NOW write a newline.
sw.WriteLine();
But that's ugly. So we'll roll it into a method to hide it. This is called "refactoring".
public void WriteDeviceStateToStream(StreamWriter stream, WhateverTheDeviceClassIs device)
{
// Write fields in desired order of appearance in the file.
stream.Write(device.deviceID);
// There are many far superior ways to write a comma to the file,
// and I'll hear about all of them in comments, but we're keeping
// it as simple as possible for the moment.
stream.Write(",");
stream.Write(device.model);
stream.Write(",");
// Properties you just set
stream.Write(device.Availability);
stream.Write(",");
stream.Write(device.rentID);
stream.Write(",");
stream.Write(device.rentName);
stream.Write(",");
stream.Write(device.rentSurname);
stream.Write(",");
stream.Write(device.OS);
// NOW write a newline.
stream.WriteLine();
// DO NOT close the stream here. The stream belongs to the caller; make no
// assumptions about what he plans to do with it next.
}
...and in your event handler, call that method. Also note using statement for the StreamWriter. That disposes of it properly, which closes the file and so on. That's important.
private void rentSaveButton_Click(object sender, RoutedEventArgs e)
{
using (StreamWriter sw = new StreamWriter(#"D:\deviceLib.txt", true))
{
var currentUser = _list.Where(u => u.Id == int.Parse(userIDTextBox.Text)).FirstOrDefault();
var currentDevice = _list2.Where(i => i.deviceId == int.Parse(deviceIDTextBox.Text)).FirstOrDefault();
if (currentDevice != null && currentUser != null)
{
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
// Call write method
WriteDeviceStateToStream(sw, currentDevice);
// The user's going to get real tired of this messagebox real fast.
MessageBox.Show("Rent done. Thanks!");
tabControl.SelectedItem = mainTab;
}
else
{
MessageBox.Show("We don't have such device. Sorry :( ");
userIDTextBox.Clear();
deviceIDTextBox.Clear();
}
}
}
Related
My message box displays hi and his, whenever, my file has the word hello.
My project is supposed to display the messagebox hi only,
and for my code (rtbDisplay.Text = "\n"+"hey";) it override the hello word that
I type.
My project is to create a chatbox. Whenever i type in certain word, it will reply me back with the words that i choose.
File.AppendAllLines(#"C:\\Users\\L31011\\Desktop\\version17\\version17\\FinalProject\\WinRecognize\\bin\\Debug\\Chat\\messages.txt", new[] { rtbType.Text });
StreamReader sr = new StreamReader("C:\\Users\\L31011\\Desktop\\version17\\version17\\FinalProject\\WinRecognize\\bin\\Debug\\Chat\\messages.txt");
rtbDisplay.Text = sr.ReadLine();
//here
string record;
string input = "hello";
string input1 = "goodbye";
try
{
record = sr.ReadToEnd();
while (record != null)
{
if (record.Contains(input))
{
MessageBox.Show("hi");
//rtbDisplay.Text = "\n"+"hey";
}
if (record.Contains(input1))
{
MessageBox.Show("byebye");
}
else
{
MessageBox.Show("his");
}
break;
}
}
finally
{
sr.Close();
}
There are a whole bunch of things that you can do to this. First, the #"string goes here" construct (i.e., with an "at" sign as a preface to the string) means that there is no escaping needed. So you don't need to double up your backslashes (I've been writing in C# since the alpha at the end of 2000, and I didn't realize that #"c:\\some\\file.ext" would work). You can say either "c:\\some\\file.ext" or #"c:\some\file.ext" -- but #"c:\\some\\file.ext" is just weird (and too much typing).
You should read up on using using. It's simpler and clearer than try { } finally { CloseOrDispose() }.
Then there is what #ChetanRanpariya is talking about. Put a breakpoint on the first if statement, when there is "hello" somewhere in the second line to the end. Start single-stepping. Notice that you step into the first message box because of the "hello". Then continue stepping. You don't step into the second message box, because there's no "goodbye". But, there is an else. See what happens next.
By the way, is this really what you want to do? You read the first line, stick it in a text box. Then you read lines 2 through N (all in one go, and into one string) and check to see if "hello" or "goodbye" is on any of them - all in a while loop that will only ever be executed once.
Solved - Accidentally wiped the actual file of data but the ide doesn't update that file unless you reopen it so I thought the data was still in there.
I'm working on a project in C# that reads in a fake inventory and then transactions to go with that inventory in another class. I know the code is quite messy at the moment, i'm just trying to figure out one thing specifically.
this code here will read in my file "Inventory.in", check if the file exists(which it does) and then start my streamreader and readline into a string.
private void btnFill_Click(object sender, EventArgs e)
{
string strInputLine;
string inFile = "Inventory.in";
StreamReader iSR;
InvRec currInvent;
if (File.Exists(inFile))
{
iSR = new StreamReader(inFile);
strInputLine = iSR.ReadLine();
while (strInputLine != null)
{
all of it isn't there but the point of emphasis is that the
"strInputLine = iSR.ReadLine();"
does indeed give me the correct value from that file.
now moving on to my question, the second block of code from another button is below:
private void btnProcess_Click(object sender, EventArgs e)
{
string strInputVal;
string inFileName = "Transactions.in";
TransRec currTrans;
StreamReader iSR2;
transListClass transactionList = new transListClass();
InvRec inventItem = inventoryList.Retrieve();
if (File.Exists(inFileName))
{
iSR2 = new StreamReader(inFileName);
strInputVal = iSR2.ReadLine();
while (strInputVal != null)
{
my problem lies when I try and do my ReadLine() into iSR2. it gives me null instead of the value from the file I'm supposed to get. Everything is the same otherwise, it just refuses to give me the correct value. I'm following the debugger in Visual Studio 2010, so I know the file is found and exists, I see it being opened, just a null value instead of my string I need.
Thank you to anybody in advance, I appreciate it.
-Anthony
edit:
the second block of code is supposed to read from "Transactions.in" instead of the first one that reads from "Inventory.in"
Important edit:
I have noticed when i changed "Transactions.in" to "Inventory.in" in the second block of code for the process button, it reads the values from Inventory.in and gives me a proper string unlike null from Transactions.in. The file is found and is just a text file named Transactions.in that was provided by my teacher, nobody else had a problem with it.
I can't sort this weird issue out and I have tried anything and everything I can think of.
I got 5 pages, everyone of them passing variables with navigation this way:
Pass:
NavigationSerice.Navigate(new Uri("/myPage.xaml?key=" + myVariable, UriKind.Relative));
Retrieve:
If (NavigationContext.QueryString.ContainsKey(myKey))
{
String retrievedVariable = NavigationContext.QueryString["myKey"].toString();
}
I open a list on many pages and one of the pages automatically deletes an item from the list actualProject (actualProject is a variable for a string list). Then, when I go so far back that I reach a specific page - the app throws an exception. Why? I have no idea.
The code that deletes the item:
// Remove the active subject from the availible subjects
unlinkedSubjects.Remove(actualSubject);
unlinkedsubjectsListBox.ItemsSource = null;
unlinkedsubjectsListBox.ItemsSource = unlinkedSubjects;
Then the page that throws the exception's OnNavigatedTo event:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("key"))
{
actualProject = NavigationContext.QueryString["key"];
try
{
//Read subjectList from IsolatedStorage
subjectList = readSetting(actualProject) != null ? (List<String>)readSetting(actualProject) : new List<String>();
//Put the subjectList into the subjectListBox
subjectListBox.ItemsSource = subjectList;
//Set the subjectsPageTitle to the "actualProject" value, to display the name of the current open project at the top of the screen
subjectsPageTitle.Text = actualProject;
}
catch (Exception)
{
if (language.Equals("en."))
{
// Language is set to english
MessageBox.Show("Couldn't open the project, please try again or please report the error to Accelerated Code - details on the about page");
}
else if (language.Equals("no."))
{
// Language is set to norwegian
MessageBox.Show("Kunne ikke åpne prosjektet, vennligst prøv igjen eller rapporter problemet til Accelerated Code - du finner detaljer på om-siden");
}
}
}
}
Exception:
_exception {System.ArgumentException: Value does not fall within the expected range.} System.Exception {System.ArgumentException}
My theory:
The app kind of loads the currently opened and modified List. Is that possible? No idea.
So there are a number of ways to pass data between pages.
The way you have chosen is the least suggested.
You can use the PhoneApplicationService.Current dictionary but this is messy also if you have a ton of variables, doesn't persist after app shut down and could be simplified.
I wrote a free DLL that kept this exact scenario in mind called EZ_iso.
You can find it here
Basically what you would do to use it is this.
[DataContractAttribute]
public class YourPageVars{
[DataMember]
public Boolean Value1 = false;
[DataMember]
public String Value2 = "And so on";
[DataMember]
public List<String> MultipleValues;
}
Once you have your class setup you can pass it easily between pages
YourPageVars vars = new YourPageVars { /*Set all your values*/ };
//Now we save it
EZ_iso.IsolatedStorageAccess.SaveFile("PageVars",vars);
That's it! Now you can navigate and retrieve the file.
YourPageVars vars = (YourPageVars)EZ_iso.IsolatedStorageAccess.GetFile("PageVars",typeof(YorPageVars));
This is nice because you can use it for more than navigation. You can use it for anything that would require Isolated storage. This data is serialized to the device now so even if the app shuts down it will remain. You can of course always delete the file if you choose as well.
Please make sure to refer to the documentation for any exceptions you have. If you still need help feel free to hit me up on twitter #Anth0nyRussell or amr#AnthonyRussell.info
I've got a very strange issue while parsing an external XAML file. The pre-history is that I want to load an external XAML file with content to process. But I want to load as many different files as I want. That happens by unloading the old and loading the new one.
My issue is:
When I load a xaml the first time, everything is good, all as it should be.
But when I load the same xaml the second time, every entry of the object im Loading is there twice. If I run this again, every object is there three times and so on...
To debug the project yourself, download it here. The function starts at line 137 in the file "Control Panel.xaml.cs". I realy don't know what this is. Is it my fault or simply a bug? If yes, is there a workaround?
/// <summary>
/// Load a xaml file and parse it
/// </summary>
public void LoadPresentation()
{
this.Title = "Control Panel - " + System.IO.Path.GetFileName(global.file);
System.IO.FileStream XAML_file = new System.IO.FileStream(global.file, System.IO.FileMode.Open);
try
{
System.IO.StreamReader reader = new System.IO.StreamReader(XAML_file);
string dump = reader.ReadToEnd(); //This is only for debugging purposes because of the strange issue...
XAML_file.Seek(0, System.IO.SeekOrigin.Begin);
presentation = (ResourceDictionary)XamlReader.Load(XAML_file);
//Keys the resourceDictionary must have to be valid
if (presentation["INDEX"] == null || presentation["MAIN_GRID"] == null || presentation["CONTAINER"] == null || presentation["LAYOUTLIST"] == null)
{
throw new Exception();
}
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
for (int i = 0; i < topics.Count; )
{
topics.RemoveAt(i);
}
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
}
catch
{
System.Windows.Forms.MessageBox.Show("Failed to load XAML file \"" + global.file + "\"", "Parsing Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
presentation = null;
}
finally
{
XAML_file.Close();
}
}
Edit:
I have tried to serialize the object that was read from the XamlReader and in the output was nowhere any childelement... But if I pull the object out of the dictionary, the children are all there (duplicated and triplicated, but there).
I have already tried to clear the list over
topics.Clear();
and
topics=new ObservableCollection<TopicListItem>();
lv_topics.ItemsSource=topics;
Try Index.Topics.Clear() after loading the Topics into your topics object. That appears to get rid of the duplication.
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
topics.Clear();
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
Index.Topics.Clear(); //Adding this will prevent the duplication
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
In the code post topics is not declared in LoadPresentation() so naturally it will have any prior values.
I know you said you tried topics=new ObservableCollection(); but please try again. And put that IN LoadPresentation()
public void LoadPresentation()
{
ObservableCollection<TopicListItem> topics = new ObservableCollection<TopicListItem>()
I would pass filename
public void LoadPresentation(string fileName)
I get you may need to use topics outside LoadPresentation but this is debugging. If you need topics outside the return it.
public ObservableCollection<TopicListItem> LoadPresentation(string fileName)
If that does not fix it I would put a try catch block on the XAML_file.Close(); to see if something weird is not going on.
I'm trying to save two Lists of objects in the phone ApplicationSettings, but I'm stuck at a strange issue (But it's probably me making a silly mistake somewhere).
If I only save one of the lists, it works as supposed - It'll save it, and reload it when app is launched next time.
But if I try to save 2 lists, none of them seem to be saved correctly. No errors or anything, just "blankness".
See code below.
//My save method
public void Gem()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains(INDTASTNINGER_LIST))
{
settings[INDTASTNINGER_LIST] = _indtastningsListe;
}
else
settings.Add(INDTASTNINGER_LIST, _indtastningsListe);
if (settings.Contains(INDTASTNINGER_LIST2))
{
settings[INDTASTNINGER_LIST2] = _indtastningsListe2;
}
else
settings.Add(INDTASTNINGER_LIST2, _indtastningsListe2);
settings.Save();
}
//Constructor supposed to load settings
public Indtastninger()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains(INDTASTNINGER_LIST))
{
_indtastningsListe = null;
_indtastningsListe = (List<Indtastning>)settings[INDTASTNINGER_LIST];
}
if (settings.Contains(INDTASTNINGER_LIST2))
{
_indtastningsListe2 = null;
_indtastningsListe2 = (List<Indtastning>)settings[INDTASTNINGER_LIST2];
}
}
What am I doing wrong?
If I comment out the part with "list2" stuff, the first one will be saved/retrieved perfectly.
I have faced the same issue some time ago, the problem is that you only can save on the IsolatedStorage objects that are XML serializables.
if you save other object, it will work even with the debugger but when the app is restarted, all the saved data is lost.