+1-888-365-2779
Try Now
More in this section

Forums / General Discussions / Media (files) field type -- filter specific documents when displaying

Media (files) field type -- filter specific documents when displaying

8 posts, 1 answered
  1. Rico
    Rico avatar
    88 posts
    Registered:
    30 Aug 2012
    27 Mar 2013
    Link to this post
    Hi there,

    I have a custom module with a custom field of type Media (files). It allows for multiple files. So the data is stored as ContenLink[].

    On the public side, is there any way of filtering out individual documents out of this array? (ie filter by name of the document?). I have a need to filter out specific documents (they follow a naming convention) for the content item of the module based on another field (a status field).

    Greatly appreciated
  2. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    28 Mar 2013 in reply to Rico
    Link to this post
    Hi Rico,

    You can of course do this in code. Just create a new template for your e.g. DetailView. Then you can use the DataBound event to iterate through these 'Documents' aka 'ContentLinks' and filter them. Not really a filter, but you can hide them.

    I've an example on how I filter images that came out of the same field type:

    protected void detailContainer_DataBound(object sender, EventArgs e) {
     
       // Get the container
       var container = sender as DynamicDetailContainer;
     
       // Get the DataItem
       var dataArray = container.DataSource as DynamicContent[];
       var dataItem = dataArray[0];
       var images = dataItem.GetValue("Images") as ContentLink[];
     
       var imageList = new List<Telerik.Sitefinity.Libraries.Model.Image>();
       foreach (var i in images)
          imageList.Add(i.ChildItemId.GetImage());
        
       imageList.OrderBy(x => x.Title);
        
       ...
    }

    To use the GetImage() method you need to have a static class where you could add this extension method:

    using System.Linq;
    using Telerik.Sitefinity.DynamicModules.Model;
    using Telerik.Sitefinity.Libraries.Model;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Model.ContentLinks;
     
    namespace Telerik.Sitefinity {
     
       public static class DynamicContentExtensions {
           
          public static Image GetImage(this DynamicContent item, string fieldName) {
           
             var contentLinks = (ContentLink[])item.GetValue(fieldName);
             ContentLink imageContentLink = contentLinks.FirstOrDefault();
             return imageContentLink.ChildItemId.GetImage();
          }
    }

    But you can easily change it to work with Documents.
    Hope this helps?

    Kind regards,
    Daniel
  3. Rico
    Rico avatar
    88 posts
    Registered:
    30 Aug 2012
    28 Mar 2013 in reply to Daniel Plomp
    Link to this post
    Hi Daniel,

    Thanks for the response. I was starting to do something similar. A question though -- you do state that i can't filter the items out, but can hide them (fair enough); however in your code I can't see how you do that (you performa  sort)... I can add in logic as follows to only add the documents to the array of ContentLinks I'd only like to display (my filter).
    within detailContainer_DataBound method:...

    var detailContainer = (DynamicDetailContainer)sender;
    var dc = ((DynamicContent[])detailContainer.DataSource)[0];
    var docList = new List<Telerik.Sitefinity.Libraries.Model.Document>();
    var additionalDocuments = (ContentLink[])dc.GetValue("MyDocuments");
    foreach (ContentLink c in additionalDocuments)
    {
    var document = libraryManager.GetDocument(c.ChildItemId);
    if (document != null)
    {
    if (document.Title.Contains("MyFilter"))
    {
    docList.Add(document);
    }
    }
    }

    However, what exactly do I bind to now on the page? Originally I was simply binding as follows (in my template)

    <sf:AssetsField runat="server" DataFieldName="MyDocuments" ID="MyDocuments" />        
    I'm assuming I have to change this in my template and bind to my underlying list (docList) -- but I'd still like to have the same 'look/feel' as the default AssetsField control. Is this possible? Am I being dumb and all I need to do is change the underlying datasource of the AssetsField to my List (doclist)?

    Thanks again!

  4. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    28 Mar 2013 in reply to Rico
    Link to this post
    Hi Rico,

    Yeah sorry, my code wasn't that complete. The AssetField also takes the Guid(s) and gets the Document urls back, if I'm correct.

    You could leave that AssetField for what it is and maybe use a repeater. So in that case you just bind for example a List<Document> containing Documents to that Repeater. Then you would have more control.

    Another way would be to filter the Documents and keep track of the Guids. Then you could assign a (new) array to the AssetField from the code-behind and the AssetField will do the rest.

    Just some thoughts...

    Kind regards,
    Daniel
  5. Rico
    Rico avatar
    88 posts
    Registered:
    30 Aug 2012
    28 Mar 2013 in reply to Daniel Plomp
    Link to this post
    Hi Daniel,

    How exactly can you assign a new array to the AssetsField control (pardon my ignorance here)? I'm having troubles understanding how this control gets bound to a datasource. It appears the only 'datasource' attribute of this control is the 'DataFieldName' -- which from what I gather is the Title of the field that it's bound to (the default way the sitefinity does it via the UI) ?

    Also, by re-defining a new array to re-bind.. won't there be issues here due to the Page lifecycle? Remember, we're currently already in the onDatabound event of the dynamicContainer...so rebinding won't really work at this point properly I don't think... ?

    It's lame that you can't just redefine some of the attributes on the contentLinks themselves during the OnPreRender event of the AssetsField control... in that event I can get access to the actual documents themselves, and there's even a 'Visible' property to assign -- would have been great that if you set Visible=false, then that document doesn't render...

  6. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    28 Mar 2013 in reply to Rico
    Link to this post
    Hi Rico,

    I'm not on a development machine right now, so I can't lookup some code.
    Probably it isn't that easy to 'assign-an-array', without a custom implementation of the AssetField control.

    The AssetField control is taking the value of the field that you enter in the DataFieldName property. This is the Guid[] you were talking about.
    Then this AssetsField control will lookup those Documents and will create a List<Document> that will be the DataSource of a DownloadListView (which is probably a Repeater or RadListView). This will then in the end be the output that is rendered.

    I can check it tonight, but I still think the easiest way is to bind your filtered List<Document> to a Repeater control which will be the same approach the AssetsField uses, but you will end up with much cleaner code ;)

    Kind regards,
    Daniel
    Answered
  7. Rico
    Rico avatar
    88 posts
    Registered:
    30 Aug 2012
    28 Mar 2013 in reply to Daniel Plomp
    Link to this post
    Hi Daniel,

    Brilliant, thanks again. Got it all working. Took your advice and used a Repeater. :-)
  8. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    28 Mar 2013 in reply to Rico
    Link to this post
    Okay, great!

    Kind regards,
    Daniel
8 posts, 1 answered