JerryShaw 46 Posting Pro in Training

Have you checked your reference properties for the DLL, and make sure it is not set to version specific ?

JerryShaw 46 Posting Pro in Training

There is a good example at:
http://support.microsoft.com/kb/308507

If this is a clean Select statement to get the data from the databaes, then this works (SqlCommandBuilder). If your data comes from multiple joins you may want to manually post the data back using your own T-SQL code, or a stored procedure.
To find out what has changed in your datagridview (underlying datatable), you can use the underlying datatable's GetChanges method:

DataTable changes = XYZ.GetChanges(DataRowState.Modified);

Iterate through the changes and post the data back to the database.

// Jerry

JerryShaw 46 Posting Pro in Training

You can search for C# XPATH on Google for tons of information on this subject. I am not sure you will find exactly what you are looking for.

There may be a better alternative, or atleast worth your time to look at, and that is to use the existing power built into the DataSet class.

For example, you can create your own XML file based database by creating a DataSet with tables, and columns (the schema). You can load this dataset from a file, and make your changes, then save it back to the file.
Lets say you have a DataSet named Config that has several tables.
When your application starts, it can check to see if you have a file named MyConfig.xml, and if so then load it.

Config.ReadXml("MyConfig.xml");

Now your application has all of the tables for this dataset loaded with data and ready to be used. Later when you want to save your changes back to the file:

Config.AcceptChanges();
Config.WriteXml("MyConfig.xml",XmlWriteMode.WriteSchema);

Now because you have all of your data in the DataSet, you can use the standard (robust) features to search, filter, etc. this data.

foreach(DataRow data in Config.Tables["Items"].Select("Index=10"))
{
      MessageBox.Show( (string)data["Damage"] );
}

Hope this helps,
Jerry

JerryShaw 46 Posting Pro in Training

I may be wrong, but I think you are asking on how to make a static class that all other classes can use.

You can change your classGlobal.cs to be static by changing the class definition to public static class classGlobal.
You will need to set your public properties and methods in this class to also be static.

When one of your other classes want to use something from classGlobal, just state it as classGlobal.Methodxyz();

Static classes do not have constructors, and you cannot or should not try to instanciate it. It is automatically instantiated when the application starts, and is immediately available to all of the application.

Hope this helps,
Jerry

JerryShaw 46 Posting Pro in Training

I don't think it is a wrong thing to say at all.

LinkedList<T> is a generic replacement for the old style coded Linked List.

JerryShaw 46 Posting Pro in Training

Maybe this link will help
http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=1
It includes some C# examples, and reasons for the different type declarations.

JerryShaw 46 Posting Pro in Training

Maybe this link wil help you understand linked lists.

http://www.c-sharpcorner.com/UploadFile/jeradus/UsingLinkedListInCS11102005005525AM/UsingLinkedListInCS.aspx

Too bad they are still teaching these prehistoric methods.
Since Generics were introduced, link lists are pretty much useless in the real world.

// Jerry

JerryShaw 46 Posting Pro in Training

First, you should decide if you are going to use the Wizard created class or stick with your own connection objects. Personnally I hate the wizard created class, it is more trouble than it is worth.

Storing the location of the Access data file and the connection string can be either setup in your Settings.Settings, or create an XML file to hold that information. Then when the application first starts, check to see if these items have been assigned, and if not, give the user a form that will allow them to setup that information. You probably need that setup form anyway in case they decide to move the file, or change the connectionstring.

// Jerry

JerryShaw 46 Posting Pro in Training

Simple... Just set e.Handled to true
When e.Handled is set to true, then the keypress event stops there, otherwise it is passed up the chain to the TextBox.
// Jerry

JerryShaw 46 Posting Pro in Training

As Scott said, use YourStringVariable.IndexOf("Value to Search")
and then use the SubString method to extract what you want.

JerryShaw 46 Posting Pro in Training

External assemblies come in two flavors. Referenced (required at startup), and dynamically loaded at some point when the program wants to use some feature within the external assembly. Dynamically loading and managing assemblies is not automatic. You have to write code to manage these external assemblies.

If this isn't very clear, then search on Google for "C# Plugin", and you will find ample information on the subject. (over 6mil refs)

JerryShaw 46 Posting Pro in Training

I have read about this is several books, and it appears that you will need to build a method that will take the array as a parameter, move all the elements except for the one you want to delete and return the new array.
Something like this where you want to delete element [0]
oPerson =DeleteArrayElement(oPerson, 0);

private ViewerList[] DeleteArrayElement(ViewerList[] value, int index)
        {
            if (index >= value.Length )
                throw new IndexOutOfRangeException();
            
            List<ViewerList> newArray = new List<ViewerList>();
            for (int i = 0; i < value.Length; i++)
            {
                if (i != index)
                    newArray.Add(value[i]);
            }
            return newArray.ToArray();
        }
JerryShaw 46 Posting Pro in Training

Ramy,
I was under the same impression that you were, that he just wanted a count of all the words, his reply showed what he really wanted.

Agreed, that a Quick sort is not as efficient or reliable, but since we brought the whole text into a variable in both yours and my examples instead of streaming the data throug a Tree sort algo, we already shot efficiency and the memory foot-print in the foot.

Do you have a tree sort algo up your sleeve that can work with a stream ?

// Cheers, Jerry

JerryShaw 46 Posting Pro in Training

Something like this:

static void Main(string[] args)
        {
            string text = "bobby crossed the road and fell on the road"; //File.ReadAllText("C:\\SomeFile.txt");
            char[] separator = new char[1] { ' ' };
            string[] textData = text.Split(separator, StringSplitOptions.RemoveEmptyEntries); 
            Array.Sort(textData);
            textData = DoWordCounts(textData);
            foreach (string str in textData)
                 Console.WriteLine(str.ToLower());
            Console.ReadKey();
        }

        private string[] DoWordCounts(string[] value)
        {
            List<string> sb = new List<string>();
            string word = string.Empty;
            int cnt = 0;
            for (int i = 0; i < value.Length; i++)
            {
                if (value[i] != word)
                {
                    if (sb.Count > 0)
                        sb[sb.Count - 1] += " " + cnt.ToString();
                    word = value[i];
                    cnt = 1;
                    sb.Add(word);
                }
                else
                    cnt++;
            }
            if (sb.Count > 0)
                sb[sb.Count - 1] += " " + cnt.ToString();
            return sb.ToArray();
        }

// Jerry

JerryShaw 46 Posting Pro in Training

Please mark it as solved, only you can do that.

JerryShaw 46 Posting Pro in Training

ASP or WinForm ?
I can help if it is a Window Form...

JerryShaw 46 Posting Pro in Training

Code Project just got a new Chat project added this week, suggest you check that out. If your chat works on the network, then is should work in the internet as well unless it is just a UDP client.
http://www.codeproject.com/KB/miscctrl/SimpleMessenger.aspx

JerryShaw 46 Posting Pro in Training

Thanks Guys, this is a major help.... I sure I will be back with more questions.
In C# the conversion was string xyz = Total.ToString("X4");

or if I still want an array then:

int Total = 123;
char[] checkSum = new char[5]; 
Array.Copy(Total.ToString("X4").ToCharArray(), checkSum, 4);

// Thanks, I have marked this as Solved, great job guys..

JerryShaw 46 Posting Pro in Training

Thanks for the quick response & the link.

So in my example, I would expect the 123 long to be formated as follows:

checkSum = 01230
or checkSum = 007B0

See my delima ? checkSum is a char[5], and the sprintf format suggests that it will insert a value that is 4 in length, left padded with 0's and will be X hex format ?

In C#, if I start with char[5] I end up with char[5], So I assume the last char will remain as an untouched 0.

So which value does checkSum become ?

// Jerry

JerryShaw 46 Posting Pro in Training

Hello,

I typically hang out in the C# forum, however I hope someone here can help.
I am converting a C++ program to C#, and I need to know how to handle a couple things: IOW I know almost nothing about C++, and this code is coming from a non dot-net version of C++

//char m_Command[30]; // <- is a class declared variable and is populated with data.
int nLength=0;
char checkSum[5];
long Total=123;

for(i=0;i<5;i++)
{
	checkSum[i]=0;	
}

sprintf(checkSum,"%04X",Total);

Can someone tell me what happens to checkSum with this sprintf method ?
I think I can formulate the string.Format syntax on my own once I know what this method is doing, but if you have a C# suggestion, I am open to that too.

Thanks in advance...

JerryShaw 46 Posting Pro in Training
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        // Class level variable
        private IDatabaseWriter _myDbWriter = null;
        private string _demoMode = "yes";

        public Form1()
        {
            InitializeComponent();
            if (_demoMode == "yes")
                _myDbWriter = new MessageTwo();
            else
                _myDbWriter = new MessageOne();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _myDbWriter.writeMsg("Hello World");
        }

    }
    public interface IDatabaseWriter
    {
        void writeMsg(string value);
    }

    public class MessageOne : IDatabaseWriter
    {
        public void writeMsg(string value)
        {
            MessageBox.Show("Write to the real database: " + value);
        }
    }

    public class MessageTwo : IDatabaseWriter
    {
        public void writeMsg(string value)
        {
            MessageBox.Show("Write to a test file for demo mode: " + value);
        }
    }
}

I assume this was just some example code you sent earlier.. and that you are not really naming things that way. All Interface classes should start with a capital 'I' iow IDatabaseWriter

As you obviously already know, but for newbies to the concept of Interfaces, let me say that what acidburn is doing is creating an Interface file (the IDatabaseWriter). An interface defines what public methods and properties must exist in any class that derives from that interface.

acidburn has two classes, one for writing to a DB, one for writing to a Text file. Both of these classes inherit from the same Interface, and therefore have the same required methods and properties.

This allows you to create an object of that Interface type, and it can be assigned from any class that also Inherits from that same interface. …

JerryShaw 46 Posting Pro in Training

Instead of using a private bool variable, use a private variable for Form2, then you have some options...

public partial class Form1 : Form
    {
        private Form2 _form2 = null;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            _form2 = new Form2();
            _form2.FormClosed += new FormClosedEventHandler(_form2_FormClosed);
            _form2.Show();
        }

        private void _form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            _form2.Dispose();
            _form2 = null;
            button1.Enabled = true;
        }
    }

Simple, just let the Form2.FormClosed event take care of telling Form1 that it has closed, and that takes care of the _form2 var, and the button.

// Jerry

JerryShaw 46 Posting Pro in Training

What value of time does the integer represent ?
Seconds, miliseconds ?

You should be able to create a DateTime for the epoch, then add to this the integer in the integer time value as AddSeconds, or AddTicks, etc. to get the value, then as far as displaying it in your
dd/MM/yyyy format is just a formating statement.

// Jerry

JerryShaw 46 Posting Pro in Training

Lets first clean up the sql statement so you can easily view it with the debugger and see which item is null...

string sql = string.Format("INSERT INTO [Issue] (Sl_no,Date,NamePrdOrRep,NameOfDepartment,TitleOfProduction"
            +",TapeType,PurposeShooting,PurposePreview,QuantityOfTape,BoxNo,BoxName,TapeNo,IssueOrReturn) "
            + "Values( '{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}',{8},'{9}','{10}','{11}','{12}' )"
            ,issue.Sl_no.Replace("'", "''")
            ,issue.Date
            ,issue.NamePrdOrRep.Replace("'", "''")
            ,issue.Department.Replace("'", "''")
            ,issue.TitleOfProduction.Replace("'", "''")
            ,issue.TapeType.Replace("'", "''")
            ,issue.PurposeShooting.Replace("'", "''")
            ,issue.PurposePreview.Replace("'", "''")
            ,issue.QuantityOfTape
            ,issue.BoxNo.Replace("'", "''")
            ,issue.BoxName.Replace("'", "''")
            ,issue.TapeNo.Replace("'", "''")
            ,issue.IssueOrReturn.Replace("'", "''")
            );

Now with the debugger, put a break point just above the statement, and use your mouse to inspect each of the values, and see which one is null.

If you are the creator of the issue class, I suggest setting up the properties to never return null.
// Jerry

JerryShaw 46 Posting Pro in Training

To read the file you created, yes, discard the first line read (the header), then for each new line read, split the values based on the comma, and don't forget to replace the Tab character:

private void button2_Click(object sender, EventArgs e)
        {
            char[] delim = new char[2]{',','\t'};
            listView1.Items.Clear();
            TextReader file = new StreamReader(@"C:\sample.playist");
            file.ReadLine();

            string line = file.ReadLine();
            string[] values;
            while (!string.IsNullOrEmpty(line)) 
            {
                values = line.Split(delim,StringSplitOptions.RemoveEmptyEntries);
                ListViewItem item = new ListViewItem(values[0]);
                for (int i = 1; i < values.Length; i++)
                    item.SubItems.Add(values[i]);
                listView1.Items.Add(item);
                line = file.ReadLine();
            }
            file.Close();
        }
JerryShaw 46 Posting Pro in Training

Here is the Tested, and working version

private void saveButton_Click(object sender, EventArgs e)
        {
            string st1 = string.Empty;
            FileStream file = new FileStream(@"C:\Titan\sample.playist", FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(file);
            for (int col = 0; col < listView1.Columns.Count; col++)
            {
                st1 += (" " + listView1.Columns[col].Text.ToString() + "\t"); // added \r\n
            }
            sw.WriteLine(st1);
            st1 = string.Empty;
            for (int row = 0; row < listView1.Items.Count; row++)
            {
                st1 = string.Empty;
                for (int col = 0; col < listView1.Columns.Count; col++)
                {
                    st1 += string.Format("{0},\t", listView1.Items[row].SubItems[col].Text.ToString());
                }
                st1 = st1.Substring(0, st1.Length - 2);
                sw.WriteLine(st1);
            }
            sw.Flush();
            sw.Close();
        }

// Jerry
Mark as solved if this works for you.

JerryShaw 46 Posting Pro in Training

Untested modified version

private void saveButton_Click(object sender, EventArgs e)
        {
            string st1= string.Empty;
            FileStream file = new FileStream(@"C:\sample.playist", FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(file);
            for (int col = 0; col < listView1.Columns.Count; col++)
            {
                st1 += (" " + listView1.Columns[col].Text.ToString() + "\t");             
            }
            sw.WriteLine(st1);
            st1 = string.Empty;

            for (int row = 0; row < listView1.Items.Count; row++)
            {
                //st1 = "\r\n"; the writeline will take care of this
                for (int col = 0; col < listView1.Columns.Count; col++)
                {
                    // used concat operator, and string format to get things positioned right
                    // Note that each value starts with a comma.
                    st1 += string.Format("{0},\t", listView1.Items[row].SubItems[col].Text.ToString());
                }
                st1 = st1.Substring(0, st1.Length - 2); // remove the last comma and tab chars
                sw.WriteLine(st1);
            }
            sw.Flush();
            sw.Close();
        }

// Jerry

JerryShaw 46 Posting Pro in Training

SubString didn't work because you are using a 0 when you should be using a 1.
Looking further while to correct that.... back in a bit.
// Jerry

JerryShaw 46 Posting Pro in Training

You have something wrong, please post your current code that handles this task and I will take a look.

JerryShaw 46 Posting Pro in Training

Okay, so you want to have a comma seperated values file (CSV).
A common task, What I typically do is start the string with a comma
then append / concatenate all of the values ALSO including a comma so that all values are started with a comma. Now once all of the values have been appened to the line, simply take the substring starting at index 1.

for (int col = 0; col < m_StockInfoList.Columns.Count; col++)
{
    // used concat operator, and string format to get things positioned right
   // Note that each value starts with a comma.
    st1 += string.Format(",{0}", m_StockInfoList.Items[row].SubItems[col].Text.ToString());
}
st1 = st1.SubString(1); // get rid of the very first comma
sw.WriteLine(st1);

// Jerry

JerryShaw 46 Posting Pro in Training

Jerry I don't agree with you to override ToString method for such reason.
Let the ComboBox SelectedValue, SelectedText properties assigned to some Class properties that's better. http://fci-h.blogspot.com/2008/04/how-to-bind-combobox-to-array-of-object.html

Ramy,
Good discussion.
In most books that I have, the author (and this includes Microsoft best practices), any class should contain an override to the ToString method.

For example, in your blog posting there are a couple things to point out (please understand I am not trying to be critical, you are a great programmer and a wonderful help on this forum).
The first item is the comboBox1.Items.AddRange(students); line. It is not required, and does not do anything for the component because the items are automatically loaded from the DataSource property. IOW, you can comment out that line with no effect on the result.
The second item is when you do not have the ToString() override, and you request the string of the currently selected item you will get
"WindowsFormApplication1.Student" instead of the expected Text string.

MessageBox.Show( comboBox1.items[0].ToString() );

So, you can still assign the DisplayMember = "FullName"; and that works great, but when you override the Student.ToString() it is a little safer (show that in a moment), and it will always return the expected value.

public override string ToString()
        {
            if (!string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(lastName))
                return FullName;
            else
                return base.ToString();
        }

The student class does not contain any null-able properties, so this simple class would work fine, however if there are …

JerryShaw 46 Posting Pro in Training

Check out:
http://www.codeproject.com/KB/cs/hard_disk_serialno.aspx

This should get you on the right track.

// Jerry

JerryShaw 46 Posting Pro in Training

Not exactly sure what you are asking for, but it is just a string, so you can concat the other textbox values into a single label using the (+) operator.

lblResult.Text = txtName.Text + " " + nextTxtName.Text + " "; // and so on...

If this is NOT what you are trying to do then provide a sample of what you want it to look like.


// Jerry

JerryShaw 46 Posting Pro in Training

First I would suggest that you create a constructor for Emp_Details just to make it easier.

public Emp_Details( string empName, int empId, double empSalary)
{
      _EmpName = empName;
      _EmpId = empId;
      _EmpSalary = empSalary;
}

Then as you get information from the user, and want to enter it into the list you can use this contructor.
Assuming you cature the user input into variables (name, Id and salary)

myEmpDetails.Add( new Emp_Details(name, Id, salary) );

// Jerry

JerryShaw 46 Posting Pro in Training

MJV,

Ramy has provided the excepted and standard way to do this.
If you are looking for something a little more extreme, then check out :
http://www.codeproject.com/KB/combobox/multicolumncombo.aspx

You may also want to explore the abilty to store tons of data to be associated with each combobox item. The item is of type Object. This means that you can create a class with all kinds of properties (even an entire dataset, datatable, datarow, etc. in this class and then add that as the Item to the combobox. The only requirement is that the class has an override ToString() method that will return the text you want displayed in the combobox and its dropdown.
Anytime you want to get at the underlying data of the item, just cast it to the type you assigned, and you have everything you want.

Hope this helps,
Jerry

JerryShaw 46 Posting Pro in Training

http://www.amazon.com/Programming-NET-Components-Juval-Lowy/dp/0596102070/ref=sr_1_1?ie=UTF8&s=books&qid=1240018238&sr=1-1

The O'Reilly book by Juval Lowy named Programming .NET Components is a good resource.

The Serialization of a class to a byte array that can then be placed into a database record, then deserialized back again into your application at a later time is simple.
I use this technique a lot, as I have a Plugin framework that loads many DLLs as modules, forms, etc. One of the places where streaming the class comes in handy is capturing the Icon, a bunch of properties like the menu item the plugin will be loaded under, security settings and the like. The data is read in from the database, and the menus and buttons arranged according to the classes that are deserialized.

Another example is a painting program that has many layers. Rather than storing each layer in a sub-table, I just serialize the entire class collection of component properties, and place that in the database as a single record. When the user wants to see this artwork, I pull it from the database, and deserialize it, dynamically create all of the objects in the correct Z order, and render the artwork to the user (extremely fast and efficient).

// Jerry

JerryShaw 46 Posting Pro in Training

for (int col = 0; col < 3; col++)

JerryShaw 46 Posting Pro in Training

:)
You need to use the row not rows[0]

foreach (DataRow row in rows)
                {
                    Console.Write("{0} ",  row["ID"]; // rows[0]["ID"]);
                    Console.Write("{0} ", row["FIRST"]; //rows[0]["FIRST"]);
                    Console.Write("{0} ", row["AGE"]; //rows[0]["AGE"]);
                    Console.WriteLine();
                }
JerryShaw 46 Posting Pro in Training

The rows array contains all rows where column [First] = 'Lance' so all you need to do is iterate through the array of rows.

DataRow[] rows = table.Select("[First]='Lance'");
foreach(DataRow row in rows)
{
      Console.Write("{0} ", row["ID"]);
      Console.Write("{0} ", row["FIRST"]);
      Console.Write("{0} ", row["AGE"]);
      Console.WriteLine();
}

BTW, there is a second parameter for the select method that allows you to set the order the rows are returned in.

// Jerry

JerryShaw 46 Posting Pro in Training

To use the select, try this:

DataRow[] rows = table.Select("[First]='Lance'");
if(rows.Length > 0)
{
      Console.Write("{0} ", rows[0]["ID"]);
      Console.Write("{0} ", rows[0]["FIRST"]);
      Console.Write("{0} ", row[0]["AGE"]);
      Console.WriteLine();
}

// Jerry

JerryShaw 46 Posting Pro in Training

Simple, the first while loop already read through the entire data reader, so there is nothing left to read by the time you get to the last while loop.

Seems that you are going about it the hard way. Why not just use an SqlDataAdapter and fill the dtl table. That way, it automatically will get all of the columns, and the data in one method call.

Ramy Mahrous commented: Correct +7
JerryShaw 46 Posting Pro in Training

Andy,

other than a couple small errors, it worked for me.
Here is the code I used with corrections:

private void savetxt()
        {
            // Got rid of "try" because it did not have the rest of it in your sample.
            //m_stockInfolist is nothing but the listview control name 
            //string[] st = new string[m_StockInfoList.Columns.Count];
            DirectoryInfo di = new DirectoryInfo(@"c:\Extraction\");
            if (!di.Exists) // Changed to use a boolean comparitor rather than a boolean equate
                di.Create();
            StreamWriter sw = new StreamWriter(@"c:\Extraction\file.txt", false);
            sw.AutoFlush = true;
            for (int col = 0; col < m_StockInfoList.Columns.Count; col++)
            {
                sw.Write("\t" + m_StockInfoList.Columns[col].Text.ToString());
            }
            //int rowIndex = 1; // not used
            //int row = 0;      // define in for..loop instead of here
            string st1;         // assignment not required
            for (int row = 0; row < m_StockInfoList.Items.Count; row++)
            {
                //if (rowIndex <= m_StockInfoList.Items.Count) rowIndex++; Not used
                st1 = "\r\n"; // Needed a Line Return
                for (int col = 0; col < m_StockInfoList.Columns.Count; col++)
                {
                    // used concat operator, and string format to get things positioned right
                    st1 += string.Format("\t'{0}'", m_StockInfoList.Items[row].SubItems[col].Text.ToString());
                }
                sw.WriteLine(st1);
            }
            sw.Flush();  //sw.flush(); Flush .. not flush (case sensitive), besides with autoflush on, this is redundant
            sw.Close();
        }

// Jerry

JerryShaw 46 Posting Pro in Training

Looked at some of the links in this thread, and am surprised on how complicated some of these examples tend to be.

I use serialization and deserialization with a Binaryformater to store and retrieve class instances between an SQL database and a Windows form.

If you need more information on the subject, I can refer you to a wonderful book that explains it in detail, or I can supply you with a code snippet to get you started with this technique.

// Jerry

JerryShaw 46 Posting Pro in Training

Hi Ramy,

Actually, since he claims that this event handler is assigned to the Enter event, I made the assumption that this is where he wants to get the original value stored into a var that would be used later to put it back.

Basically the idea I was trying to convey is that when dealing with lots of textboxes, it is better to cast the sender, and deal with that one object rather than take its name and run though a buzillion case statements :)

BTW: Sorry for misspelling your name earlier.

// Jerry

JerryShaw 46 Posting Pro in Training

As BlackSun explained, you will need to manage it yourself using the image Graphics. It is a bit more complicated than the example above, but should move you into the right direction. The image onPaint event will have to remember that you have an active selection (the rectangle, and its deminsions) so that if you refresh the form, the selection will be persistent. You may want to use a popup menu, or something to grab that selection of the image and copy it to another bitmap object for processing (send to file, drag drop, whatever).

JerryShaw 46 Posting Pro in Training

Similar to Ramey, assuming that the event handler is only assigned to TextBox controls.

private void undotextbox(object sender, EventArgs e)
{
        TextBox textbox = sender as TextBox;
        if(textbox != null)
       {
            string oldValue = textbox.Text;
       }
}
JerryShaw 46 Posting Pro in Training

Okay, maybe you can provide more detail. Walk me through exactly what you are trying to do. I assume you have a text file that is read on startup that has something that tells you how you want to write data.
From there you want to instantiate an object that will either use a live database, or another text file for output.
So in the constructor or Load event you want to use an (if) statement to instatiate the correct type. (IOW instead of using polymorphism for a single class, you want to instantiate a specific class).
Because they both derive from the same interface it should be possible, as long as the interface defines the possible methods required for both operations.

JerryShaw 46 Posting Pro in Training

I have a project I downloaded from Code Project called fun with animation. It has 100 animations running on a background image with no flicker.
(animation.zip) is attached.
I think the key to it is under the InitializeComponents() method in the form constructor it has the following code. Maybe you can find what you need in the attached project. I use the concept in a mapping program and it works fine.

SetStyle(	ControlStyles.AllPaintingInWmPaint |
	ControlStyles.DoubleBuffer |
	ControlStyles.ResizeRedraw |
	ControlStyles.UserPaint,
	true);
JerryShaw 46 Posting Pro in Training

Are you using double buffering ?

JerryShaw 46 Posting Pro in Training

Your interface should have a few more properties, such as the server, database name, credentials. Besides that if may either subclass the writer to handle a Filename in the place of the server.
Then in your writeMsg method, you would append the text to the specified filename.