Benutzer mit den meisten Antworten
Textbox Oldvalue ( ich kanns nicht glauben)

Frage
-
Hallo Newsgroup,
ich stelle gerade ein PAket von ACCESS auf c# um.
In access wurde der oldvalue einer Textbox verwandt, nun habe ich so was nicht auf Anhieb gefunden und mühsam etwas gebastelt.
Geht das wirklich nicht einfacher?
/// <summary>
/// liefert den "oldvalue" einer Textbox
/// </summary>
/// <param name="sender">sender aus Validted </param>
/// <param name="modus">0=nur oldvalue, 1 = Änderungstext</param>
/// <returns></returns>
public static string Oldvalue(object sender, int modus)
{
if (sender is TextBox)
{
TextBox textBox = (TextBox)sender;
Binding binding = textBox.DataBindings[0];
DataRowView dataRowView = (DataRowView)binding.BindingManagerBase.Current;
DataSet set = (DataSet)dataRowView.Row.Table.DataSet;
string tabelle = dataRowView.Row.Table.ToString();
string feld = binding.BindingMemberInfo.BindingField;
DataColumnCollection dataColumnCollection = (DataColumnCollection)dataRowView.Row.Table.Columns;
int nr = dataColumnCollection[feld].Ordinal;
string oldvalue = dataRowView.Row.ItemArray[nr].ToString();
if (modus == 1)
return (feld + " geändert von >>" + oldvalue + "<< auf >>" + textBox.Text + "<<");
else
return oldvalue;
}
return null;
}Bin mal gespannt wie "blöd" ich mich angestellt habe.
Viele grüße aus dem noch nicht wieder sonnigen München
Walther Lückemann
Antworten
-
Hallo Walther,
es geht anders. Allerdings ist das Thema dort um einiges komplexer gelöst als beim guten alten Access.
Und Dein Code in der jetzigen Form wird je nach Zeitpunkt der Verwendung und Status der Zeile
so nicht (ganz) richtig funktionieren.Im Vergleich zu Access verwaltet die DataTable mehrere Versionen, siehe DataRowVersion .
Welche Versionen zur Verfügung stehen, hängt vom Status der Zeile ab, der durch den DataRowState festgelegt wird.
So gibt es bei einer neuen Zeile keine Orginalwert und bei einer gelöschten nur noch einen Orginalwert.
Bei einer geänderten wiederum den aktuellen und den Originalwert.Und nur während der Bearbeitung findet sich der derzeitig zwischenspeicherte Wert als vorgeschlagener (Proposed) Wert.
Was voraussetzt, dass die Datenbindung die Werte mindestens einmalig übertragen hat,
was sie je nach Binding.DataSourceUpdateMode zu unterschiedlichem Zeitpunkt tut.Meine Frage wäre: Was willst Du mit der Funktion überhaupt lösen.
Ich - der sich selbst mal intensiv mit Access beschäftigt hat - habe das Konzept eines OldValues
bei .NET relativ schnell at akta gelegt, da es für die Forms Datenbindung wenig nützlich ist.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 20. August 2010 13:02
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
-
Hallo Walther,
Im einfachsten Fall kann man einfach "[STRG-Z]" oder "textBox.DataBindings[0].ReadValue();" oder "bindingSource.CancelEdit();" benutzen, wenn noch keine interne Bearbeitung abschlossen wurde (in diesem Fall, wenn man z.B. in der TextBox verbleibt).
Wenn doch, dann benutzt man normalerweise die Ableitung von IEditableObject. Im folgenden Artikel benutzt der Author zum Beispiel eine generische Klasse "ObjectBase", von der er sein Business-Object ableitet, sodass automatisch CancelEdit() zur Verfügung steht:
[Discard changes in business objects - CodeProject]
http://www.codeproject.com/KB/database/IEditableObject.aspxInsofern ist das dann nur ein CancelEdit() Aufruf zum Beispiel auch des BindingSource:
[BindingSource.CancelEdit-Methode (System.Windows.Forms)]
http://msdn.microsoft.com/de-de/library/system.windows.forms.bindingsource.canceledit.aspx
was intern die the CancelCurrentEdit Methode des darunterliegenden CurrencyManager aufruft.
IEditableObject ist der empfohlene Weg seitens Microsoft. Siehe dazu u.a. den Thread [hier]:
[Linda Liu - MSFT]:
I absolutely support the opinion to discard changes in a business object by manipulating the business object itself, e.g by implementing the IEditableObject interface. The reasons are as follows.1. DataSet/DataTable is a good example that supports this opinion, which provides RejectChanges method to discard changes made to the DataSet/DataTable since the DataSet/DataTable is filled or the AcceptChanges method is called on it last time.
2. Let's say that a user loads data from underlying data store, e.g. database or web service, and made some modifications on the data and then wants to discard the last modification. Note that all the modifications haven't been saved back to the data store. In this case, the "re-load" approach doesn't work.
3. Actually the IEditableObject interface is intended to support discard changes made to an object.
ciao Frank- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 20. August 2010 13:03
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
-
Hallo Walther,
Man hat die Qual der Wahl. So ist es eben unter .NET. Da sehnt man sich schon mal nach den Selbstverständlichkeiten anderer Programmiersprachen.
Einige Möglichkeiten wurden bereits in diesem Thread vorgestellt, aber .NET bietet außer den Grundbausteinen von ADO.NET auch noch viele andere Wege. Ich wähle hier den einfachsten (ohne auf System.ComponentModel.IEditableObject und dergleichen einzugehen):using System; using System.Windows.Forms; namespace WindowsFormsApplication7 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Person person = new Person { FirstName = "Tom", LastName = "Sawyer" }; BindingSource source = new BindingSource() { DataSource = person }; textBoxEx1.DataBindings.Add("Text", source, "FirstName"); } private void buttonUndo_Click(object sender, EventArgs e) { textBoxEx1.Text = textBoxEx1.OldText; } } public class Person { public string FirstName { get; set; } public string LastName { get; set; } } public class TextBoxEx : TextBox { public string OldText { get; private set; } public TextBoxEx() { this.Enter += (sender, e) => OldText = this.Text; } } }
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
Alle Antworten
-
Hallo,
die Frage ist, was "oldvalue" denn konkret ist. Wenn es der ursprüngliche Wert in der DB, oder sonst ein einmal zugewiesener Wert ist, dann kannst Du diesen ja in die Tag-Eigenschaft schreiben und bei validating, oder ähnliches vergleichen.
Soll es jedoch immer der vorige Wert der Textbox sein, müsste man fragen, was der Auslöser für das Speichern des oldvalue ist. Ist es der jeweils neue Wert, der beim validating überprüft wird, dann könnte man diesen an eben dieser Stelle dann zuweisen.
Viele Grüße,
Thorsten
-
Hallo Walther,
es geht anders. Allerdings ist das Thema dort um einiges komplexer gelöst als beim guten alten Access.
Und Dein Code in der jetzigen Form wird je nach Zeitpunkt der Verwendung und Status der Zeile
so nicht (ganz) richtig funktionieren.Im Vergleich zu Access verwaltet die DataTable mehrere Versionen, siehe DataRowVersion .
Welche Versionen zur Verfügung stehen, hängt vom Status der Zeile ab, der durch den DataRowState festgelegt wird.
So gibt es bei einer neuen Zeile keine Orginalwert und bei einer gelöschten nur noch einen Orginalwert.
Bei einer geänderten wiederum den aktuellen und den Originalwert.Und nur während der Bearbeitung findet sich der derzeitig zwischenspeicherte Wert als vorgeschlagener (Proposed) Wert.
Was voraussetzt, dass die Datenbindung die Werte mindestens einmalig übertragen hat,
was sie je nach Binding.DataSourceUpdateMode zu unterschiedlichem Zeitpunkt tut.Meine Frage wäre: Was willst Du mit der Funktion überhaupt lösen.
Ich - der sich selbst mal intensiv mit Access beschäftigt hat - habe das Konzept eines OldValues
bei .NET relativ schnell at akta gelegt, da es für die Forms Datenbindung wenig nützlich ist.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 20. August 2010 13:02
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
-
Hallo Elmar,
erst mal (wieder) herzlichen Dank für die schnelle Antwort. Ich werde Deinen Hinweisen nachgehen.
Die Aufgabe ist schnell beschrieben. Alle Änderungen, die ein User vornimmt werden bis zum Speichern in der Form Feld wurde von auf geändert gesammelt.
Beim Speichern wird dann daraus ein Email-Vorschlag für eine Meldung an eine übergeordnete Stelle gebildet, die nicht in der Lage ist Daten automatisiert einzulesen (( :-) aber das ist deren Problem)).
Wenn Dir auf die schnelle was einfällt: Danke im Voraus. Aber ich denke, dass Dein Vorschlag schon den Weg weist.
Viele Grüße,
Walther
-
Hallo Walther,
Du kannst hier die DataTable (bzw. das gesamte DataSet) zum "Sammeln" verwenden,
ohne dabei auf Formular(e) und ihren Aufbau Rücksicht zu nehmen.
Denn durch die oben beschriebene Versionierung stehen Dir alle Daten zur Verfügung.An der Stelle wo Du ansonsten ein TableAdapter.Update vornehmen würdest,
kannst nun die DataTable auswerten, und entweder via Select die geänderten Zeilen
abrufen und Spalte für Spalte auswerden - dabei False Positives aussondern, z. B.
wenn ein Spalte hin- und zurückgeändert wurde.Ein alternativer Ansatz wäre DiffGrams zu verwenden. Damit hast Du die
erforderlichen Werte als XML vorliegen und kannst daraus Deine E-Mail aufbauen.Gruß Elmar
-
Hallo Walther,
Man hat die Qual der Wahl. So ist es eben unter .NET. Da sehnt man sich schon mal nach den Selbstverständlichkeiten anderer Programmiersprachen.
Einige Möglichkeiten wurden bereits in diesem Thread vorgestellt, aber .NET bietet außer den Grundbausteinen von ADO.NET auch noch viele andere Wege. Ich wähle hier den einfachsten (ohne auf System.ComponentModel.IEditableObject und dergleichen einzugehen):using System; using System.Windows.Forms; namespace WindowsFormsApplication7 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Person person = new Person { FirstName = "Tom", LastName = "Sawyer" }; BindingSource source = new BindingSource() { DataSource = person }; textBoxEx1.DataBindings.Add("Text", source, "FirstName"); } private void buttonUndo_Click(object sender, EventArgs e) { textBoxEx1.Text = textBoxEx1.OldText; } } public class Person { public string FirstName { get; set; } public string LastName { get; set; } } public class TextBoxEx : TextBox { public string OldText { get; private set; } public TextBoxEx() { this.Enter += (sender, e) => OldText = this.Text; } } }
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
-
Hallo Walther,
Im einfachsten Fall kann man einfach "[STRG-Z]" oder "textBox.DataBindings[0].ReadValue();" oder "bindingSource.CancelEdit();" benutzen, wenn noch keine interne Bearbeitung abschlossen wurde (in diesem Fall, wenn man z.B. in der TextBox verbleibt).
Wenn doch, dann benutzt man normalerweise die Ableitung von IEditableObject. Im folgenden Artikel benutzt der Author zum Beispiel eine generische Klasse "ObjectBase", von der er sein Business-Object ableitet, sodass automatisch CancelEdit() zur Verfügung steht:
[Discard changes in business objects - CodeProject]
http://www.codeproject.com/KB/database/IEditableObject.aspxInsofern ist das dann nur ein CancelEdit() Aufruf zum Beispiel auch des BindingSource:
[BindingSource.CancelEdit-Methode (System.Windows.Forms)]
http://msdn.microsoft.com/de-de/library/system.windows.forms.bindingsource.canceledit.aspx
was intern die the CancelCurrentEdit Methode des darunterliegenden CurrencyManager aufruft.
IEditableObject ist der empfohlene Weg seitens Microsoft. Siehe dazu u.a. den Thread [hier]:
[Linda Liu - MSFT]:
I absolutely support the opinion to discard changes in a business object by manipulating the business object itself, e.g by implementing the IEditableObject interface. The reasons are as follows.1. DataSet/DataTable is a good example that supports this opinion, which provides RejectChanges method to discard changes made to the DataSet/DataTable since the DataSet/DataTable is filled or the AcceptChanges method is called on it last time.
2. Let's say that a user loads data from underlying data store, e.g. database or web service, and made some modifications on the data and then wants to discard the last modification. Note that all the modifications haven't been saved back to the data store. In this case, the "re-load" approach doesn't work.
3. Actually the IEditableObject interface is intended to support discard changes made to an object.
ciao Frank- Als Antwort vorgeschlagen Robert BreitenhoferModerator Freitag, 20. August 2010 13:03
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 24. August 2010 14:11
-
Hallo Frank,
*vielen* Dank für diese Infos. Das ist genaau das, was ich - in anderem Kontext - brauche - und wo ich mir dann auch tatsächlich bisher mit der Tag-Eigenschaft und dem GotFocus-Event beholfen habe. Jetzt ist das viel sauberer zu lösen, danke nochmals.
Viele Grüße,
Thorsten