WorkItem's SmartPart vs. Items Collection

Topics: CAB & Smart Client Software Factory
Apr 10, 2007 at 10:24 AM
Among others, the WorkItem baseclass contains a smartPartCollection and an itemsCollection. Both accessible by their appropriate properties (WorkItem.Items, WorkItem.SmartParts). The only differece is, that the smartPartCollection just accepts objects containing the SmartPart attribute, whereas the itemsCollection accepts any object.
I'm wondering which bag to use in order to store smart parts. Actually both bags are valid. The CAB quick start samples use the items bag like:
commentsView = this.Items.AddNew<CustomerCommentsView>("CustomerCommentsView");

But the SCSF HOL uses the smart parts bag like:
ShipNewOrderView view = WorkItem.SmartParts.AddNew<ShipNewOrderView>();

I'd suggest to define a best practice in order to avoid confusion!
Apr 10, 2007 at 3:27 PM
In any case, when you add a view to the smartParts collection
it's available under the items collection as well.

To show a smartPart, I add it to the smartParts collection and then show it. I wrote a utility function, I'm not sure if you'll find it useful for doing that.

The assumption here is that I'm showing only one instance of a particular type of smartPart.

try
{
Guard.ArgumentNotNull(smartPart, "smartPart");
Guard.ArgumentNotNull(workspace, "workspace");
Guard.ArgumentNotNull(workitem, "WorkItem");

if (workitem.Status != WorkItemStatus.Active)
workitem.Activate();

if (workitem.SmartParts.FindByType(smartPart.GetType()).Count == 0)
{
workitem.SmartParts.Add(smartPart);
}
else
{
if (((Control)(((List<object>)workitem.SmartParts.FindByType(smartPart.GetType()))0)).IsDisposed)
{
workitem.SmartParts.Remove(((List<object>)workitem.SmartParts.FindByType(smartPart.GetType()))0);
try
{
workitem.SmartParts.Add(Activator.CreateInstance(smartPart.GetType()), smartPart.GetType().Name + Guid.NewGuid());
}
catch { }
}
smartPart = ((Control)(((List<object>)workitem.SmartParts.FindByType(smartPart.GetType()))0));
}
if (smartPartInfo != null)
workspace.Show(smartPart, smartPartInfo);
else
workspace.Show(smartPart);
}
catch (Exception exc){throw exc;}
Apr 10, 2007 at 3:50 PM

They are the same collection. The only difference is that by using the SmartParts property, you're getting a subset of the larger collection.

I'd suggest to define a best practice in order to avoid confusion!

There's nothing stopping you from adopting your own best practice for consistency :-)

In our shop we try and standardize by always use SmartParts collection when dealing with views. But it's purely a syntactic decision for consistency. Either way works.

Apr 10, 2007 at 7:18 PM
THEY ARE NOT THE SAME COLLECTION !!!!

These Items and SmartParts are entirely two different collections and not the same as you see below.

1.

WorkItem.SmartParts - Returns a collection describing the child smart parts (objects with the SmartPartAttribute applied to them) in this WorkItem.

WorkItem.Items - Gets a list of all the objects and services contained in this WorkItem.

2. Two different variable declarations in CAB sources WorkItem.cs

private ManagedObjectCollection<object> smartPartCollection;

public ManagedObjectCollection<object> SmartParts
{
get { return smartPartCollection; }
}


private ManagedObjectCollection<object> itemsCollection;


public ManagedObjectCollection<object> Items
{
get { return itemsCollection; }
}

3. If you need custom attributes of a smartpart, you can't get it if you add into Items collection . See this Init() code in WorkItem.cs:

if (itemsCollection == null)
{
itemsCollection = new ManagedObjectCollection<object>(lifetime, locator, builder,
SearchMode.Local, null, null, parent == null ? null : parent.itemsCollection);
}

if (smartPartCollection == null)
{
smartPartCollection = new ManagedObjectCollection<object>(lifetime, locator, builder,
SearchMode.Local, null, *delegate(object obj)
{
return obj.GetType().GetCustomAttributes(typeof(SmartPartAttribute), true).Length > 0;
},*
parent == null ? null : parent.smartPartCollection);
}
4. Both collections are having different parents collection. You can't get it if you add vice versa.

So, always use SmartParts collection to add your user controls and Items for any other objects & services.

Cheers, Venkat
Apr 11, 2007 at 11:12 PM
Wow. My bad. I had to go look at the code to make sure that was real.

They are separate collections, albiet with the same lifetime containers and locators.

So yeah, follow Venkat's advice: use SmartPart collection for your SmartParts.

Don't listen to silly old me.
Apr 13, 2007 at 5:25 PM
I have a related question. I'm using the Infragistics dock and MDITab workspaces. I have some smartparts that I only want to display one instance of. When I show them the first time, I call dockworkspace.addnew() and dockworkspace.show().

Now what? If the smartpart is still displayed and they choose the command to show it again, I want to call Activate, correct? But if they closed it, what do I want to do? It seems like it gets removed from the smartparts collection, but not from the Items collection. However, trying to show it again tries to add it to the items collection a second time, which causes an error. One would think CAB provides me a way to deal with this gracefully, and perhaps I simply haven't found it yet!

Kevin
Apr 25, 2007 at 5:01 PM
If the view is marked as smartpart and it is added to the items collection in the workitem, does it add it to the smartpart collection as well?
I read on another thread that the smartparts collection is only a facade to the items collection.