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 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);
}
}
}
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.
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);
}
}
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();
}
}
}
This ended up being a bigger problem than I envisioned. There are lot
of issues with binding to the same record or row. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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="*"...
|
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...
|
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...
|
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. ...
|
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...
|
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....
|
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...
|
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...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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...
|
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,...
|
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...
|
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...
| |