User login |
data bindingAdding EntitiesOnce a BindingSource is hooked to a LinQ EF query, editing/deletion become trivial. But how about adding new objects? My first attempt, it turns out, was just backwards: I added a new object to the EntitySet and then added that new object to the BindingSource. While this worked, it causes havoc in the ObjectStateManager - key inconsistencies, etc. Turns out the pattern is this: Add a new object via the BindingSource: User u = (User)UserVarBindingSource.AddNew(); That's it. The new object is created and added to the underlying list (in this case the EntitySet) and the BindingSource will position itself (and all bound Controls) to the new records. But that's not quite the end of the story - the new object probably requires some type of initialization and if that's explicitly done in a default constructor then it needs to be done as a result of the add operation. We make use of the BindingSource's AddingNew event to set a flag indicating that a new object is added:
private void UerBindingSource_AddingNew( object sender, AddingNewEventArgs e )
{
m_adding = true;
}
Then utilizing the CurrentChanged event (after the object is added the BindingSource sets it as the current object, triggering this event) the new object is initialized:
private void UserBindingSource_CurrentChanged( object sender, EventArgs e )
{
// adding new object flag set in AddingNew event handler
if ( ! m_adding )
return;
// reset the flag so we don't modify every object viewed
m_adding = false;
//
// fetch the new object and dress it up
Model.User usr = (Model.User)UserBindingSource.Current;
sv.name = "NoName";
....
// The object is stil in the 'edit' state which means the changes will not
// be propogated to the underlying layer - end the edit so the object is "live".
sysVarBindingSource.EndEdit();
}
The call to EndEdit is important - either at this point or prior to saving the data: if EndEdit isn't called, the BindingSource does not propogate changes to the underlying data store (hmmmmmm.... undo anyone?).
Binding Entities to Form ControlsBinding Entities to Forms controls - easily done but not easily divined. The naive would hook a LinQ query to the BindingSource's DataSource - and would be rewarded with a functional binding - most of the time. In fact for read only lists of things this may be acceptable (adding/deleting objects causes inconsitencies in the ObjectManager). One piece of advice I ran across is to not use this type of binding because every time the BindingSource moves to a different record it rexecutes the query (not confirmed by my testing but it may be true) which could be handy in a highly concurrent environment. After much gnashing and googling I came across the "proper" way to do this (actually it's in book: "Programming Entity Framework" - O'Reilly"):
ObjectQuery<User> query;
...
query = ( from var in m_model.Users
orderby var.sortorder, var.name
select var
) as ObjectQuery<User>;
userBindingSource.DataSOurce = query;
As long as you cast the LinQ query to a ObjectQuery<T>, the BindingSource coordinates everything properly.
Typing: The query is run on the EntitySet while the ObjectQuery<T> is typed to the underlying object.
|