Extend BindingSource with a Dirty property and Dirty changed Event
-
Hello, I'm building a database WinForm application. The data objects in my first application where based up on SQLDataConnector, DataSet, DataTables and SQLDataAdapter. Now I moved on and I write Data object classes, which I fill with a SqlDataReader. Modifying the record is done by straight INSERT, UPDATE and DELETE queries written in a Data Object DB Class. The technique is out of the book => Murach's ADO.Net 3.5 LinQ and the Entity Framework. After studying different technique I decided not to go for Entity Framework but hang around with writing my own data classes, making use of binding with data objects and most important ... understanding what happens under the Engine Cowling. So far so GOOD. The client interface works fine, but I like to give the User feedback as soon she/he is changing the content in one of the bounded controls (Textbox, comboBox, ect). In such case I like to show a pencil Icon on the form indicating the content has been changed. So I like to capture an event as soon the record becomes "DIRTY". This way I can decided if an Update is required when the user clicks the button "Save and Close" (just like with leaving a MS Outlook contact form). If the 'IsDirty' property is 'false' the form just should close. Else it should write the changes back to the SQL server in advance of closing. I studied the BindingSource control, but I cannot find an 'IsDirty' property as well no event related to this. I found some articles on the web indicating the same problem. But the code samples are not providing a solution for me. CONCREET: I like to customize the BindingSource by simply adding an "IsDirty" property and an "IsDirtychanged" event. Will this be an easy one???? Your help is most appreciated! With kind regards, Arjen Groeneveld
-
Hello, I'm building a database WinForm application. The data objects in my first application where based up on SQLDataConnector, DataSet, DataTables and SQLDataAdapter. Now I moved on and I write Data object classes, which I fill with a SqlDataReader. Modifying the record is done by straight INSERT, UPDATE and DELETE queries written in a Data Object DB Class. The technique is out of the book => Murach's ADO.Net 3.5 LinQ and the Entity Framework. After studying different technique I decided not to go for Entity Framework but hang around with writing my own data classes, making use of binding with data objects and most important ... understanding what happens under the Engine Cowling. So far so GOOD. The client interface works fine, but I like to give the User feedback as soon she/he is changing the content in one of the bounded controls (Textbox, comboBox, ect). In such case I like to show a pencil Icon on the form indicating the content has been changed. So I like to capture an event as soon the record becomes "DIRTY". This way I can decided if an Update is required when the user clicks the button "Save and Close" (just like with leaving a MS Outlook contact form). If the 'IsDirty' property is 'false' the form just should close. Else it should write the changes back to the SQL server in advance of closing. I studied the BindingSource control, but I cannot find an 'IsDirty' property as well no event related to this. I found some articles on the web indicating the same problem. But the code samples are not providing a solution for me. CONCREET: I like to customize the BindingSource by simply adding an "IsDirty" property and an "IsDirtychanged" event. Will this be an easy one???? Your help is most appreciated! With kind regards, Arjen Groeneveld
ArjenGroeneveld wrote:
I studied the BindingSource control, but I cannot find an 'IsDirty' property as well no event related to this.
The
BindingSource
has aCurrentItemChanged
-event[^] that might be of help.ArjenGroeneveld wrote:
CONCREET: I like to customize the BindingSource by simply adding an "IsDirty" property and an "IsDirtychanged" event. Will this be an easy one????
Meh, that's an unfair question! It would include subclassing the
BindingSource
, adding a field, an event, and the wiring for it. You'd also need a testproject, time and documentation - and you can ask additional questions here :)I are Troll :suss:
-
ArjenGroeneveld wrote:
I studied the BindingSource control, but I cannot find an 'IsDirty' property as well no event related to this.
The
BindingSource
has aCurrentItemChanged
-event[^] that might be of help.ArjenGroeneveld wrote:
CONCREET: I like to customize the BindingSource by simply adding an "IsDirty" property and an "IsDirtychanged" event. Will this be an easy one????
Meh, that's an unfair question! It would include subclassing the
BindingSource
, adding a field, an event, and the wiring for it. You'd also need a testproject, time and documentation - and you can ask additional questions here :)I are Troll :suss:
Okay, Can you help me with the code? Kind regards Arjen
-
Okay, Can you help me with the code? Kind regards Arjen
ArjenGroeneveld wrote:
Okay, Can you help me with the code?
If you want to save the Dirty-field along with the binding, then I'd suggest overriding the
Binding
class, and not theBindingSource
. This might give you a start for a test-form, and having a property in a derived class, using databinding;using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;namespace Example
{
public class MyBinding : Binding
{
bool _isDirty;
public bool IsDirty
{
get
{
return _isDirty;
}
set
{
if (_isDirty != value)
_isDirty = value;
}
}public MyBinding(string propertyName, object DataSource, string dataMember) :base(propertyName, DataSource, dataMember) { // more stuff!! } } public class Form1 : System.Windows.Forms.Form { static void Main() { Application.Run(new Form1()); } private TextBox textBox1; private ListBox listBox1; private MyBinding myBinding; public Form1() { InitializeComponent(); } private void InitializeComponent() { SuspendLayout(); listBox1 = new ListBox(); textBox1 = new TextBox(); textBox1.Location = new Point(16, 68); textBox1.Size = new Size(144, 20); listBox1.Location = new Point(16, 8); listBox1.Size = new Size(144, 50); ClientSize = new Size(176, 100); Controls.Add(textBox1); Controls.Add(listBox1); Name = "Form1"; Text = "Form1"; Load += new EventHandler(Form1\_Load); ResumeLayout(false); } private void Form1\_Load(object sender, System.EventArgs e) { DataTable dt = new DataTable("employee"); dt.Columns.Add("firstname"); dt.Columns.Add("lastname"); dt.Rows.Add("john", "doe"); dt.Rows.Add("johnny", "walker"); listBox1.DataSource = dt; listBox1.DisplayMember = "firstname"; myBinding = new MyBinding("Text", listBox1.DataSource, "lastname"); textBox1.DataBindings.Add(myBinding); } }
}
Enjoy :)
I are Troll :suss:
-
ArjenGroeneveld wrote:
Okay, Can you help me with the code?
If you want to save the Dirty-field along with the binding, then I'd suggest overriding the
Binding
class, and not theBindingSource
. This might give you a start for a test-form, and having a property in a derived class, using databinding;using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;namespace Example
{
public class MyBinding : Binding
{
bool _isDirty;
public bool IsDirty
{
get
{
return _isDirty;
}
set
{
if (_isDirty != value)
_isDirty = value;
}
}public MyBinding(string propertyName, object DataSource, string dataMember) :base(propertyName, DataSource, dataMember) { // more stuff!! } } public class Form1 : System.Windows.Forms.Form { static void Main() { Application.Run(new Form1()); } private TextBox textBox1; private ListBox listBox1; private MyBinding myBinding; public Form1() { InitializeComponent(); } private void InitializeComponent() { SuspendLayout(); listBox1 = new ListBox(); textBox1 = new TextBox(); textBox1.Location = new Point(16, 68); textBox1.Size = new Size(144, 20); listBox1.Location = new Point(16, 8); listBox1.Size = new Size(144, 50); ClientSize = new Size(176, 100); Controls.Add(textBox1); Controls.Add(listBox1); Name = "Form1"; Text = "Form1"; Load += new EventHandler(Form1\_Load); ResumeLayout(false); } private void Form1\_Load(object sender, System.EventArgs e) { DataTable dt = new DataTable("employee"); dt.Columns.Add("firstname"); dt.Columns.Add("lastname"); dt.Rows.Add("john", "doe"); dt.Rows.Add("johnny", "walker"); listBox1.DataSource = dt; listBox1.DisplayMember = "firstname"; myBinding = new MyBinding("Text", listBox1.DataSource, "lastname"); textBox1.DataBindings.Add(myBinding); } }
}
Enjoy :)
I are Troll :suss:
Hello, The end result I have in mind is an extended BindingSouce control, which is having an "IsDirty" property and an "IsDirtyChange" event. The "IsDirtyChange" should only trigger when the User is making a change in one of the bounded controls. I did some searching in FrameWork and I put the following together, but this code does not trigger when a user changes the content in a control. So something is missing. Extended BindingSource coding... namespace ACMAD.Business { class exBindingSource : BindingSource { // Internal variable private bool flgIsDirty = false; // Event public event EventHandler IsDirtyChanged; protected virtual void OnDirtyChanged(EventArgs e) { if (IsDirtyChanged != null) { IsDirtyChanged(this, e); } } public bool IsDirty { get { return flgIsDirty; } set { flgIsDirty = value; } } protected override void OnBindingComplete(BindingCompleteEventArgs e) { base.OnBindingComplete(e); if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) { if (!flgIsDirty && (e.BindingCompleteState == BindingCompleteState.Success) && e.Binding.Control.Focused) { flgIsDirty = true; OnDirtyChanged(EventArgs.Empty); } } } protected override void OnCurrentChanged(EventArgs e) { base.OnCurrentChanged(e); if (flgIsDirty == true) flgIsDirty = false; } } } Form coding I placed the exBindingSource on the form and connected an textbox to it. One record is loaded with: // Test purpose exBindingSource1.Clear(); exBindingSource1.Add(ac_Model); And I added an event private void exBindingSource1_IsDirtyChanged(object sender, EventArgs e) { textBox1.Text = exBindingSource1.IsDirty.ToString(); } The idea is that when the user makes a change to Textbox1 that Textbox2 is filled with the exBindingSource1.IsDirty value. But ... nothing happens.. Your help is most appreciated. With kind regards, Arjen Groeneveld
-
Hello, The end result I have in mind is an extended BindingSouce control, which is having an "IsDirty" property and an "IsDirtyChange" event. The "IsDirtyChange" should only trigger when the User is making a change in one of the bounded controls. I did some searching in FrameWork and I put the following together, but this code does not trigger when a user changes the content in a control. So something is missing. Extended BindingSource coding... namespace ACMAD.Business { class exBindingSource : BindingSource { // Internal variable private bool flgIsDirty = false; // Event public event EventHandler IsDirtyChanged; protected virtual void OnDirtyChanged(EventArgs e) { if (IsDirtyChanged != null) { IsDirtyChanged(this, e); } } public bool IsDirty { get { return flgIsDirty; } set { flgIsDirty = value; } } protected override void OnBindingComplete(BindingCompleteEventArgs e) { base.OnBindingComplete(e); if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) { if (!flgIsDirty && (e.BindingCompleteState == BindingCompleteState.Success) && e.Binding.Control.Focused) { flgIsDirty = true; OnDirtyChanged(EventArgs.Empty); } } } protected override void OnCurrentChanged(EventArgs e) { base.OnCurrentChanged(e); if (flgIsDirty == true) flgIsDirty = false; } } } Form coding I placed the exBindingSource on the form and connected an textbox to it. One record is loaded with: // Test purpose exBindingSource1.Clear(); exBindingSource1.Add(ac_Model); And I added an event private void exBindingSource1_IsDirtyChanged(object sender, EventArgs e) { textBox1.Text = exBindingSource1.IsDirty.ToString(); } The idea is that when the user makes a change to Textbox1 that Textbox2 is filled with the exBindingSource1.IsDirty value. But ... nothing happens.. Your help is most appreciated. With kind regards, Arjen Groeneveld
I've added a theoretical
OnCurrentItemChanged
, but my DataGridView won't let me edit the collection. I can't test the code until tomorrow :(protected override void OnCurrentItemChanged (System.EventArgs e)
{
base.OnCurrentItemChanged (e);
if (IsDirty == false)
IsDirty = true;
}I are Troll :suss:
-
Hello, The end result I have in mind is an extended BindingSouce control, which is having an "IsDirty" property and an "IsDirtyChange" event. The "IsDirtyChange" should only trigger when the User is making a change in one of the bounded controls. I did some searching in FrameWork and I put the following together, but this code does not trigger when a user changes the content in a control. So something is missing. Extended BindingSource coding... namespace ACMAD.Business { class exBindingSource : BindingSource { // Internal variable private bool flgIsDirty = false; // Event public event EventHandler IsDirtyChanged; protected virtual void OnDirtyChanged(EventArgs e) { if (IsDirtyChanged != null) { IsDirtyChanged(this, e); } } public bool IsDirty { get { return flgIsDirty; } set { flgIsDirty = value; } } protected override void OnBindingComplete(BindingCompleteEventArgs e) { base.OnBindingComplete(e); if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) { if (!flgIsDirty && (e.BindingCompleteState == BindingCompleteState.Success) && e.Binding.Control.Focused) { flgIsDirty = true; OnDirtyChanged(EventArgs.Empty); } } } protected override void OnCurrentChanged(EventArgs e) { base.OnCurrentChanged(e); if (flgIsDirty == true) flgIsDirty = false; } } } Form coding I placed the exBindingSource on the form and connected an textbox to it. One record is loaded with: // Test purpose exBindingSource1.Clear(); exBindingSource1.Add(ac_Model); And I added an event private void exBindingSource1_IsDirtyChanged(object sender, EventArgs e) { textBox1.Text = exBindingSource1.IsDirty.ToString(); } The idea is that when the user makes a change to Textbox1 that Textbox2 is filled with the exBindingSource1.IsDirty value. But ... nothing happens.. Your help is most appreciated. With kind regards, Arjen Groeneveld
Hi, just want to ask if you solve your question, because right now I'm having problem same as yours, I would be thankful if you can share it, thanks. By the way, what type of your datasource you used in extended bindingDataSource? thank you.. :)