Realtime updating textfield messages in winforms - c#

I have a service that add items to a class and then serialize a class into a file.
Then I need to create a simple form C# with a textfield (multiline) showing realtime from the deserialized file.
I will have timer every second that will read my List of a property of the class and show it in a textfield.
My question here is:
Is there a way that instead of reading again and again the file I can just get the latest rows added and just append to the textfield?

var file = File.OpenRead("abc.txt");
file.Seek(1000, SeekOrigin.Begin);
Reading a file, use "Seek" to skip old data.

just a suggestion:
I think, you should rather use some sort of message queue for this purpose.
Again per your post, instead of directly fetching from file, it would be good if you rather store the deserialized content in a stack. That way, you can always get the content from top of the stack.

Related

Exception while saving data into a txt file

I am trying to write the data to a file, and the data is continuously updated every 100ms. So when I click save button then
System.InvalidOperationException: Collection was modified enumeration operation may not execute.
error comes up. Upon my search there is solutions to this probelm if there is Foreach loop but in my case there is no Foreach loop.
Bellow is the code I used
File.WriteAllLines(fileDialog.FileName,
RawDataFromSerialPort.Select((v, i) => $"{i + 1} Raw data is -->, {v.ToString()}"));
I'd say your serial port is still receiving data on a background thread whilst you're trying to read from the raw data collection, I'd suggest making a copy of the collection and then writing the copy out to the file.
Try using the syncroot property on the collection while doing the copy.
https://learn.microsoft.com/en-us/dotnet/api/system.array.syncroot?view=netframework-4.7.2
Check the stacktrace as well, there you'll find the drill down of the call stack where eventually a foreach-(like)loop is used.
Click on the 'view details' link, expand the $exception node and look for the StackTrace field.
The problem was that the List name I was accessing was wrong so correcting the list name RawDataFromSerialPort made my problem solved

Regarding WPF, need advice on data sources and data binding

I am not new to WPF, but I am still a rookie. Let's say, I want to build an application which stores data about a person in an unique and separate file, and not in a database, sort of, like, Notepad. My application should do the following things.
It should be able to save a person's info in an unique file.
It should be able to open an user specified file and auto fill the properties/form.
How do I achieve this? Is the XML binding only way to achieve this, or is there an any other alternative? What I mean is, If I use XML binding I can write code which will enable the user to open and save different XML files, but I also read that binding to XML should be avoided from the architecture perspective. So, is there an alternative solution for my problem?
I think if you try doing the stuff by using a Reading and writing the things to a CSV(Comma separated values) file(If not planning to implement databases) then you can achieve what you wanted.
Also if you are planning to have a separate file for each user its not at all a good idea.
Its not possible to explain everything thing here . So please have a look to link posted below , in which it has explained in detail how to achieve Reading and Writing to a csv file .
This example has been posted from here for getting full detail please look to following link Reading and writing to a csv file
Apparently your requirement is to save person details into a unique file. If you really want to use that approach, one option is using XMLSerialization.
You can create your normal person object for data binding.
When you want to save data into the specific person's file you can serialize the object and save file with a proper name (person id or so)
When you want to get Person data back from the file, you can deserialize the it directly to a person object.
// Serialize and write to file
Person person = myPerson;
var serializer = new XmlSerializer(person.GetType());
using (var writer = XmlWriter.Create("person1.xml"))
{
serializer.Serialize(writer, person);
}
// Deserialize back to an instance
var serializer = new XmlSerializer(typeof(Person));
using (var reader = XmlReader.Create("person1.xml"))
{
var person= (Person)serializer.Deserialize(reader);
}
For saving user data, such as sessions and settings. There are plenty of ways you can do this.
Saving to data to txt files. See here.
Saving data to a database. See here.
My personal favourite, saving to the Settings file. See here.
These are only some of the ways you can save data locally.
Note that I mentioned saving data to a database because it is something that you shouldn't completely knock, especially if you will be saving lots of data.
To answer your question more directly, I would suggest that you go with option 3. For relatively small sets of data, like user info and user settings, it would be your best bet to save them to the built in Settings file. It's dead easy.
Good luck!

What the most efficient way of monitoring changes to data on an ASP.Net form?

I have an ASP.Net form and I want to send an email when the user changes their data. The email should only include data that has changed, and there are about 15 data fields total.
I don't want to use an ORM since I am updating a website that a 3rd party built for us, and all their data access calls go through a custom library of theirs.
The only ways to do this I can think of is
Make another database call to get old values and compare the form values one-by-one. If they're different, append to the email.
Store original data somewhere when it's first loaded (hidden field, session, etc), and once again compare the data one field at a time and append the differences to an email
Have someone on SO tell me there's an easier and/or simpler way that I haven't thought of
All the text boxes will have a TextChanged event, you can have them mark themselves as modified. ComboBox's will have a SelectedIndexChanged event, and so on.
Edit: All changed events can check their initial values (even on reverted changes) and either mark themselves as still modified or on a revert, as un-modified.
Here are some suggestions that may / may not be useful:
Trigger on the database table and the trigger compares the old (using the DELETED table) and updated (using the INSERTED table) and then sends an email. This may or may not be viable and I am not a big advocate of triggers.
Like you have already said you could make another database call, which would be my reccommended approach.
From what you've said I think that the only way forward is to create a duplicate dataset on the form to store the old data and run a comparison at the point where you want to produce the email.
You can use Dataset.Copy to copy structure and data.
However, now that I think about it there's always the Datset.GetChanges() method and the Dataset.AcceptChanges() along with DataSet.HasChanges()
Example code from this link:
if(dataSet.HasChanges(DataRowState.Modified |
DataRowState.Added)&& dataSet.HasErrors)
{
// Use GetChanges to extract subset.
changesDataSet = dataSet.GetChanges(
DataRowState.Modified|DataRowState.Added);
PrintValues(changesDataSet, "Subset values");
// Insert code to reconcile errors. In this case, reject changes.
foreach(DataTable changesTable in changesDataSet.Tables)
{
if (changesTable.HasErrors)
{
foreach(DataRow changesRow in changesTable.Rows)
{
//Console.WriteLine(changesRow["Item"]);
if((int)changesRow["Item",DataRowVersion.Current ]> 100)
{
changesRow.RejectChanges();
changesRow.ClearErrors();
}
}
}
}
// Add a column to the changesDataSet.
changesDataSet.Tables["Items"].Columns.Add(
new DataColumn("newColumn"));
PrintValues(changesDataSet, "Reconciled subset values");
// Merge changes back to first DataSet.
dataSet.Merge(changesDataSet, false,
System.Data.MissingSchemaAction.Add);
}
PrintValues(dataSet, "Merged Values");

How to get instance of object from XML file?

I have XML file of object.I want to get instance of that object.But i dont have class.I must read XML and create dynamically how to say class. How to do?
See this page, it can help but you need .NET 4.
I guess you want to read data from an XML into your class. If so, you can use the following way to read the data from a file.
var records = from r in XElement.Load(#"YourFile.xml").Elements("NodeName")
select r;

How to save Large Data to file

I have list of maybe 50,000 entries that are populated in datagrid in wpf. Now I want to save the data in the list to a file that may be text, or preferably CSV. As list is too big. There is a problem that my implemented method that may be simple text file writing or the method to copy the contents from the datagrid to clipboard and then back to string, and then that string to file using StreamReader. It consumes approx 4-5 minutes even it is in background worker.
Is there any way that I can save huge list to file quickly?
I am using DataGrid in WPF
CODE
dataGrid1.SelectAllCells();
dataGrid1.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader;
ApplicationCommands.Copy.Execute(null, dataGrid1);
String result = (string)Clipboard.GetData(DataFormats.CommaSeparatedValue);
///Never reach to step Below thread stays on above line
dataGrid1.UnselectAllCells();
Clipboard.Clear();
StreamWriter file = new System.IO.StreamWriter(SavePageRankToPDF.FileName);
file.WriteLine(result);
file.Close();
Instead of using the clipboard, why not iterate through the datatable and build the csv file.
Update
Here are some examples:
Convert DataTable to CSV stream
Converting DataSet\DataTable to CSV
One thing that will help is to not load ALL of your data into the datagrid when using it for display purposes. It'd be a good idea to use paging: only load the data into the datagrid that will be needed for calculations or display purposes. If the user wants to see/use more data, go back to your data source and get more of the data. Not only will your app run faster, you'll use much less memory.

Categories