Working with collections

Topics: Developer Forum
Aug 13, 2008 at 9:31 PM
Edited Aug 14, 2008 at 9:30 AM
Hi there


This has got me stumped and I'm sure that I'm missing something simple. I'd like to be able to manage a child collection from within a content item. As an example, if I have a ContentItem named "Product" and wish the product to have a collection of images related to it I think I need to set it up as follows:



	public class Product : N2.ContentItem
{
[EditableFreeTextArea("Description", 500)]
public virtual string Text
{
get
{
return (string)(GetDetail("Description") ?? String.Empty);
}
set
{
SetDetail("Description", value, String.Empty);
}
}

protected DetailCollection _Images
{
get
{
return GetDetailCollection("Images", true);
}
}
public IList<ProductImage> Images
{
get
{
return _Images.ToList<productimage>();
}
}
public void AddImage(ProductImage image)
{
_Images.Add(image);
}
public void AddImages(IEnumerable<ProductImage> images)
{
_Images.AddRange(images);
}
}

however, how would I view these images within the CMS?

Thanks

Graham

Coordinator
Aug 13, 2008 at 10:08 PM

Not beeing sure about the nature of your problem I'll take a shot:

  • You're saving your product after adding images? (N2.Context.Persister.Save)
  • You're displaying your images in a repeater of some sort?
    <% foreach(productimage i in CurrentPage.Images) { %>
        <img src='<%= i.Src %>'/>
    <% } %>
Aug 14, 2008 at 9:35 AM
Hi there

Yes the above assumptions are correct. My question is quite a general one, and not just about images. For example I intend my product to have a List<string> of Tags that will be displayed on the page as well, so I guess I'm looking for advice on how any types of collections are expected to be populated via the N2 admin interface.

Should I be looking at implementing my own custom editors for this task?

Thanks so much for your help!

Graham
Coordinator
Aug 14, 2008 at 4:37 PM
I'd probably go for a custom editor. There is one that assumes you want to store the items as child nodes with a zone name.
Aug 29, 2008 at 9:50 AM
Cristian, what would you suggest on the following problem:
Suppose, I have a bag of properties, either as Details collection OR as DetailCollection collection. I'd also like to avoid creating custom editor for Details, resorting to one you've mentioned above for Children. Is it possible to fool N2 by exposing Details collection as a sub-set of Children collection, so that i'll have EditableChildrenAttribute work for Details? Consider the following pseudo-code:

//Intended only for wrapping StringDetails for editing
public class FakeItem: N2.ContentItem {}

using System.Linq;
//Another, "true" item with StringDetails, editable by EditableChildren editor
public class MyItem: N2.ContentItem {
...
public override List<ContentItem> Children {
  get { return base.Children.Concat(
    //Append details, wrapped as "fake" items ...
      from _detail in this.GetDetailCollection("MyDetails", false)
      select new FakeItem { Name = _detail.Name, Title = _detail.StringValue, }
    ).ToList();
  }
  set {
    //Store "true" children
    base.Children = value.Select(_child => !(_child is FakeItem)).ToList();
    //Store "fake" children as Detail
    foreach(var _detail in this.GetDetailCollection("MyDetails", false)) {
       _detail.StringValue = value.OfType<FakeDetail>().Single(_child => _child.Name).Title;
    }
  }
}

More preciselly, the question is: where (and when) to inject "fake" items so the editor would be able to read them and store back ? virtual "Children" collection? Overriding either of 3 virtual GetChildren(..) methods ? Which one, then ?

Thank you :-)
Coordinator
Aug 29, 2008 at 11:52 PM
Hi, I'd go for the GetChildren(string zoneName). It's the one used by the editable children. It's also used when getting parts to the zone web control.

The general idea is that Children should represent what's in the database and the GetChildren can be used to manipulate what's displayed in various interfaces.