New Posts New Posts RSS Feed: [SOLVED] ListConverterServiceBase Method
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

[SOLVED] ListConverterServiceBase Method

 Post Reply Post Reply Page  <12
Author
Bill Jensen View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Jul-2007
Location: United States
Posts: 229
Post Options Post Options   Quote Bill Jensen Quote  Post ReplyReply Direct Link To This Post Topic: [SOLVED] ListConverterServiceBase Method
    Posted: 22-Oct-2007 at 3:54pm

Keep walking, man...

As I mentioned, your ListConverter will need to listen for the CurrentChanged event of the binding source and refresh the list.  This will cause the predicate to be re-evaluated for each member of the list.
 
B.
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2007 at 4:40pm

I have the Event Pub/Sub working fine, so the app knows when the customer changes on the sales order; however, how do I tell the BindingSource of the ListConverter to refresh?  This is a bit of a mystery.  In the ListConverterServiceBase, the "hack" iterates the binding sources and reset the bindings on each one.  In what way am I to call just the binding source of the list that is populating the control on my view?

Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2007 at 5:12pm
I tried adding the ListConverter to the RootWorkItem Items collection:
 
WorkItem.RootWorkItem.Items.Add(converter, "BillToListConverter");
 
Then, in the view's presenter, I added the EventSubscription:
 
[EventSubscription(EventTopicNames.SalesOrderCustomerChange)]
public void OnChangeCustomer(object sender, DataEventArgs<int> e)
{
    //somehow update the view's address list
    ListConverter mConverter = WorkItem.RootWorkItem.Items.Get<ListConverter>("BillToListConverter");
    mConverter.ListSource.ResetBindings(false);
}
 
This is getting called every time I change the customer number (navigate to a different sales order, type a customer number, pick customer from list, etc.).  The predicate is *not* running, though.  It runs the first time the converter is created, but not any subsequent times.  Is there another way to get the list converter to refresh?
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 22-Oct-2007 at 5:38pm
Here's how I referenced the ListConverter (rather than adding it to the RootWorkItem items collection):
 
ListConverter mConverter = ListConverterService.Get(ListConverterNames.BillToList);
 
That works nicely. 
 
Now, the next problem...the parent binding source (SalesOrder) is not being retrieved from the WorkItem.  It keeps coming up with the current value of null in the EntityBindingSource.  Am I doing something wrong in the page controller with this code?
 
WorkItem.RootWorkItem.Items.Add(MainBindingSource, "SalesOrderBindingSource");
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 9:51am
As soon as I did this (instead of trying to use the WorkItem) in the ListConverterService:
 
[EventSubscription(EventTopicNames.SalesOrderCustomerChange)]
public void OnChangeCustomer(object sender, DataEventArgs<int> e)
{
    mCustIndex = e.Data;
}
 
...the ListConverter stopped reevaluating when I sent the ResetBindings command.  I can walk the code through to the ResetBindings command, but it now does not engage the predicate.  Why would the addition of the EventSubscription changed things?


Edited by Linguinut - 23-Oct-2007 at 9:51am
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 10:17am
Let me summarize a little:
 
In an attempt to understand the AddListManager_KeepExistingEntitiesOnly(converter) method in ListConverterServiceBase, I embarked on a journey to see if a filter could be applied using a similar approach.  I added the following code to the ListConverterService in the Foundation module:
 
protected void AddListManager_FilteredList<T>(EntityListConverter<T> pListConverter, EntityColumn pColumn) where T : Entity
{
    mColumn = pColumn;
    EntityList<T> aList = (EntityList<T>)pListConverter.ListSource.List;
    EntityListManager<T> listManager = new EntityListManager<T>
        (pListConverter.EntityManager.PersistenceManager,
        IsExistingEntity,
        null);
    aList.ListManager = listManager;
}
 
private bool IsExistingEntity<T>(T pEntity) where T : Entity
{
    if (mCustIndex == (int)pEntity.GetColumnValue(mColumn.ColumnName)) { return true; };
    return false;
}
 
[EventSubscription(EventTopicNames.SalesOrderCustomerChange)]
public void OnChangeCustomer(object sender, DataEventArgs<int> e)
{
    mCustIndex = e.Data;
}
 
private int mCustIndex = 0;
private EntityColumn mColumn;
 
I have removed comments for brevity.  In my sales order module, and on the view that presents the sales order data (including customer), I added the EventPublication code.  I am not reproducing it here since it it not directly relevant.  In my view that presents the address list, I have the following code running:
 
[EventSubscription(EventTopicNames.SalesOrderCustomerChange)]
public void OnChangeCustomer(object sender, DataEventArgs<int> e)
{
    ListConverter mConverter = ListConverterService.Get(ListConverterNames.BillToList);
    mConverter.ListSource.ResetBindings(false);
}
 
Note that both the ListConverterService and my AddressView are listening to the customer number change.  The ListConverterService updates the variable that stores the current customer index which will be used in the predicate.  The AddressView fires off a ResetBindings on the listconverter underlying the list control on the form.  This looks like it should work, but once I introduced the EventSubscription to the ListConverterService, the ResetBindings no longer evaluated the objects in the list by using the predicate.
 
What fundamental principle am I violating that would cause this?
 
Thanks,
Bill
Back to Top
Bill Jensen View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Jul-2007
Location: United States
Posts: 229
Post Options Post Options   Quote Bill Jensen Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 11:25am

ResetBindings may not do the job.  Try

EntityList<T> aList = (EntityList<T>)pListConverter.ListSource.List;

EntityListManager<T> listManager = (EntityListManager<T>)aList.ListManager;

listManager.RefreshAllLists();
 
Moreover, since there is only one ListConverter with these filtering conditions (and hence only one ListManager), you could keep the ListManager around in the ListConverterService (in a mListManager member along with mCustIndex and mColumn),  then put
 
mListManager.RefreshAllLists()
 
in the event hander in the service.  Then you don't need the event handler in your view.
 
There are other factoring and coupling considerations, but we'll discuss those later.
 
Bill J.
 
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 12:12pm
The aList.ListManager is an implementation IListManager.  The EntityListManager<T> has the RefreshAllLists method.  Looks like I would have to sacrifice generics in order to make this work, since I need an EntityListManager object to do the work.  Right?
Back to Top
Bill Jensen View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Jul-2007
Location: United States
Posts: 229
Post Options Post Options   Quote Bill Jensen Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 1:10pm
Why?  You created it here:
 
protected void AddListManager_FilteredList<T>(EntityListConverter<T> pListConverter, EntityColumn pColumn) where T : Entity
{
    mColumn = pColumn;
    EntityList<T> aList = (EntityList<T>)pListConverter.ListSource.List;
    EntityListManager<T> listManager = new EntityListManager<T>
        (pListConverter.EntityManager.PersistenceManager,
        IsExistingEntity,
        null);
    aList.ListManager = listManager;
}
 
Can't you just cast it back to an EntityListManager<yourtype>.
 
 
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 1:16pm
I cast it back in the EventSubscription.  I was trying to do it elsewhere.
 
Here is my adjusted code that works...
 
protected void AddListManager_FilteredList<T>(EntityListConverter<T> pListConverter, EntityColumn pColumn) where T : Entity
{
    mColumn = pColumn;
    EntityList<T> aList = (EntityList<T>)pListConverter.ListSource.List;
    EntityListManager<T> listManager = new EntityListManager<T>
        (pListConverter.EntityManager.PersistenceManager,
        IsExistingEntity,
        null);
    aList.ListManager = listManager;
    mListManager = aList.ListManager;
}
 
private bool IsExistingEntity<T>(T pEntity) where T : Entity
{
    if (mCustIndex == (int)pEntity.GetColumnValue(mColumn.ColumnName)) { return true; };
    return false;
}
 
[EventSubscription(EventTopicNames.SalesOrderCustomerChange)]
public void OnChangeCustomer(object sender, DataEventArgs<int> e)
{
    mCustIndex = e.Data;
    EntityListManager<AddressMaster> mBillToListManager = EntityListManager<AddressMaster>)mListManager;
    mBillToListManager.RefreshAllLists();
}
 
private IListManager mListManager;
private int mCustIndex = 0;
private EntityColumn mColumn;
 
Bill...thanks for all of your help on this.  Now, that I have gotten it working, I will try to separate the functionality a bit more so that I can reuse the code for other entity lists.  For now, I am glad that it works.
Back to Top
Bill Jensen View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Jul-2007
Location: United States
Posts: 229
Post Options Post Options   Quote Bill Jensen Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 3:04pm

Great.  Glad to hear it's working.  There are a few structural issues to consider:

1.  Currently, the ListConverterService knows about the event topic and holds the member variables used by the predicate.  It might be better to create a custom ListConverter class ("SynchronizedCustomerListConverter") that inherits from EntityListConverter<Customer>.  It could add the ListManager (perhaps using a generic method in the ListConverterService) but retain the member variables, predicate and subscribe to the event topic.

2.  Since there is actually only one "SynchronizedCustomerListConverter", all views that use it will be synchronized to the same customer index published by the SalesOrderCustomerChange event.  This presumes there is one master selected customer for the entire application.  If you needed to edit sales orders for two different customers simultaneously (in popup windows for example) this mechanism would break down.
 
3.  An alternative is to not use the ListConverterService at all, but let the presenter of the view containing the customer combo box create it and supply it to the view.  The presenter could then learn of the binding source holding the current customer (from its view context) and subscribe to its CurrentChanged event.  When the current customer changed, it would refresh the list, either using the predicate mechanism or by re-querying and assigning to the binding source.
 
Bill J.
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 23-Oct-2007 at 3:11pm
I am pondering the first approach.  #2 will definitely need to be considered as I lay this out.
 
#3 didn't seem to work, unless I wasn't doing something correctly.  The problem with the this approach was that the list would not synch with the parent entity.  I would have a filled list with the proper filtered data, but it would always default to none selected.  Somehow the reassigning of the binding source corrupted the original controlbindingmanager.
 
Thanks for the additional tips!
Back to Top
orcities View Drop Down
Senior Member
Senior Member
Avatar

Joined: 28-Aug-2007
Location: United States
Posts: 454
Post Options Post Options   Quote orcities Quote  Post ReplyReply Direct Link To This Post Posted: 24-Oct-2007 at 1:51pm
Bill,
 
I have been doing your (3) example. Letting the presenter control the information. The problem is that I, on occassion, don't get the correct response. For example the combo box will fill with the data needed but it will not bind the current item to it.
 
Or you can select an item in the box but it never holds. As soon as you leave the box it goes back to being blank. The value is usually set correctly but it will not keep the current selection in the box.
 
Do you know why this could be happening.
Back to Top
Linguinut View Drop Down
Senior Member
Senior Member
Avatar

Joined: 14-Jun-2007
Location: United States
Posts: 394
Post Options Post Options   Quote Linguinut Quote  Post ReplyReply Direct Link To This Post Posted: 24-Oct-2007 at 6:01pm
I did get the same behavior on the .NET controls.  The DevEx LookUpEdit control works like a charm.  I am systematically replacing all .NET controls with DevEx controls (grids, toolbars, textboxes, etc.).  By the way, I just got a license for the controls.
 
Also, I am using the two-stage approach to the ListConverters (per Cabana examples).  One ListConverter is for the master list designed to display the proper string.  The second ListConverter is a copy of the first but is designed for the primary index of the entity.  When I add a LookUpEdit, I am binding it to the foreign key field, not the related entity list.  So far, this is working nicely for me (although, I have not dug into how this two-stage approach works).
 
Is anything that I said different than what you are doing?
 
Bill
Back to Top
 Post Reply Post Reply Page  <12

Forum Jump Forum Permissions View Drop Down