473,394 Members | 1,766 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Writing a Custom BindingList for Mapping between DataObjects andDataTables

Hello:

I have a mapping class that can take generic data objects and locate/
add/remove/update DataRows in a DataTable. I associate them using
attributes: TableAttribute and ColumnAttribute. I use reflection to
move the data between the data object and the DataTable.

I would like to make this extremely easy for my Forms developers.

I would like calling AddNew() to call mapper.AddDataRow(dataObject).

I would like changes to call mapper.UpdateDataRow(dataObject).

I would like removing to call mapper.DeleteDataRow(dataObject).

I am trying to implement this. Right now, I am inheriting from
BindingList<DataObject>. However, I am not sure which methods to
override and where to place my code. A quick example would be awesome.
I get the impression this should be easy to do; I just don't know how
to do it correctly.

Also, I would like to know what is the best method for preventing the
addition a bogus values to the BindingList<T>. How can I prevent them
from adding NULL or and instance of U?

Thanks!
~Travis
Aug 27 '08 #1
5 3976
This is what I have right now:

public class DataObjectBindingList<TDataRecord:
BindingList<TDataRecord>
where TDataRecord : class, new()
{
private readonly IDataTableMapper<TDataRecordmapper;

public DataObjectBindingList(IDataTableMapper<TDataRecord >
mapper)
{
Check.CheckArgumentNull(mapper, "mapper");
this.mapper = mapper;
}

protected override void OnAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
object adding = e.NewObject;
if (!(adding is TDataRecord))
{
throw new InvalidOperationException("Items must be of
type "
+ typeof(TDataRecord).FullName
+ " and non-null");
}
}

public override void EndNew(int itemIndex)
{
TDataRecord record = this[itemIndex];
mapper.AddDataRow(record);
base.EndNew(itemIndex);
}

protected override void RemoveItem(int index)
{
TDataRecord record = this[index];
mapper.DeleteDataRow(record);
base.RemoveItem(index);
}

public void Update()
{
foreach (TDataRecord record in Items)
{
mapper.UpdateDataRow(record);
}
}
}
Aug 27 '08 #2
I am currently forcing the developer to call Update(). This isn't good
because it will make it look like every record was changed. I could
change how UpdateDataRow works by having it check whether the updated
value is changing before altering the DataRow, but that could get
ugly.

There isn't really a way to tell whether an object is changed. I mean,
I could check whether the class supports INotifyPropertyChanged and
listen, but managing the events doesn't sound like much fun either.
Aug 27 '08 #3
Here is the latest version. I realized that most of the code I wrote
before wasn't necessary.

public class DataObjectBindingList<TDataRecord:
BindingList<TDataRecord>
where TDataRecord : class, new()
{
private readonly IDataTableMapper<TDataRecordmapper;
private readonly Dictionary<TDataRecord,
PropertyChangedEventHandlerhandlers;

public DataObjectBindingList(IDataTableMapper<TDataRecord >
mapper)
{
Check.CheckArgumentNull(mapper, "mapper");
this.mapper = mapper;
if
(typeof(INotifyPropertyChanged).IsAssignableFrom(t ypeof(TDataRecord)))
{
handlers = new Dictionary<TDataRecord,
PropertyChangedEventHandler>();
}
}

protected override void InsertItem(int index, TDataRecord
item)
{
if (handlers != null && !handlers.ContainsKey(item))
{
PropertyChangedEventHandler handler = new
PropertyChangedEventHandler(itemChanged);
((INotifyPropertyChanged)item).PropertyChanged +=
handler;
handlers[item] = handler;
}
mapper.AddDataRow(item);
base.InsertItem(index, item);
}

protected override void SetItem(int index, TDataRecord item)
{
if (handlers != null && !handlers.ContainsKey(item))
{
PropertyChangedEventHandler handler = new
PropertyChangedEventHandler(itemChanged);
((INotifyPropertyChanged)item).PropertyChanged +=
handler;
handlers[item] = handler;
}
base.SetItem(index, item);
}

protected override void RemoveItem(int index)
{
TDataRecord record = this[index];
mapper.DeleteDataRow(record);
PropertyChangedEventHandler handler;
if (handlers != null && handlers.TryGetValue(record, out
handler))
{
((INotifyPropertyChanged)record).PropertyChanged -=
handler;
}
base.RemoveItem(index);
}

private void itemChanged(object sender,
PropertyChangedEventArgs e)
{
mapper.UpdateDataRow((TDataRecord)sender);
}
}
Aug 27 '08 #4
I realized that if the code modifies the primay key, I can't map back
to the DataRow. I had to think about this one.

I have written a Binding class that will bind a property to a column
in a DataRow. It works but worries me.

public class Binding
{
private readonly object instance;
private readonly PropertyInfo property;
private readonly DataRow row;
private readonly string columnName;
private readonly DataRowChangeEventHandler rowChangedHandler;
private readonly PropertyChangedEventHandler
propertyChangedHandler;

public Binding(object instance, PropertyInfo property, DataRow
row, string columnName)
{
this.instance = instance;
this.property = property;
this.row = row;
this.columnName = columnName;
rowChangedHandler = new
DataRowChangeEventHandler(rowChanged);
row.Table.RowChanged += rowChangedHandler;
if (instance is INotifyPropertyChanged)
{
INotifyPropertyChanged item =
(INotifyPropertyChanged)instance;
propertyChangedHandler = new
PropertyChangedEventHandler(propertyChanged);
item.PropertyChanged += propertyChangedHandler;
}
}

private void updateRecord()
{
INotifyPropertyChanged item = instance as
INotifyPropertyChanged;
try
{
if (item != null)
{
item.PropertyChanged -= propertyChangedHandler;
}
object value = row[columnName];
value = TypeCaster.ConvertTo(value,
property.PropertyType);
property.SetValue(item, value, null);
}
finally
{
if (item != null)
{
item.PropertyChanged += propertyChangedHandler;
}
}
}
private void updateRow()
{
try
{
row.Table.RowChanged -= rowChangedHandler;
row[columnName] = property.GetValue(instance, null);
}
finally
{
row.Table.RowChanged += rowChangedHandler;
}
}

private void rowChanged(object sender, DataRowChangeEventArgs
e)
{
if (e.Action == DataRowAction.Change && e.Row == row)
{
updateRecord();
}
}

private void propertyChanged(object sender,
PropertyChangedEventArgs e)
{
if (e.PropertyName == property.Name)
{
updateRow();
}
}
}
Aug 28 '08 #5
This ended up being a bigger problem than I envisioned. There are lot
of issues with binding to the same record or row.
Aug 28 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Mauricio | last post by:
Hí! I´m implementing a web application using the Front Controller pattern described in the Enterprice Solutions Patters using Microsoft .NET v 1.0 In order to map an absolute path to...
7
by: Adam | last post by:
Im trying to add an httphandler for all *.sgf file extensions. I have developed the handler, 1. installed it into the gac 2. added it to the machine.config: <httpHandlers> <add verb="*"...
4
by: hazz | last post by:
The data access layer below returns, well, a mess as you can see on the last line of this posting. What is the best way to return customer objects via a datareader from the data layer into my view...
0
by: g18c | last post by:
Hi, i have a class which has a property which is a list of items. I want to be able to set this item list from a set of items (in this case list2 as shown in the code below) from a drop down combo...
1
by: Dave Booker | last post by:
Is there a reason why the BindingList constructor doesn't create a new BindingList? Create a form with four ListBoxes and the following will result in them all containing the exact same thing. ...
3
by: Monty | last post by:
I've created an object (called cMyBindingList) that inherits from BindingList. I can serialize it and it's child items with no problem. However, I've also created a public variable in...
4
by: Stuart | last post by:
I hope someone can shed some light on an error I've been experiencing for sometime now, but can no longer continue to ignore :-( I've created a custom entity class which implements IEditableObject....
0
by: Pieter | last post by:
Hi, I'm using NHibernate 1.2 (CR1), and I'm using a custom list (inherited from BindingList(Of T) ) for all my lists. The NHibernate documentation told me that I had to implement...
3
by: jimmarq | last post by:
Please help me with this databinding scenario: Suppose I have a "Person" class, and that users populate Person objects in a BindingList collection through a datagridview. Users save the Person...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.