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

Posted by Community Admin on 03-Aug-2018 22:51

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

All Replies

Posted by Community Admin on 27-Mar-2013 00:00

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

Posted by Community Admin on 28-Mar-2013 00:00

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

Posted by Community Admin on 28-Mar-2013 00:00

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!

Posted by Community Admin on 28-Mar-2013 00:00

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

Posted by Community Admin on 28-Mar-2013 00:00

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...

Posted by Community Admin on 28-Mar-2013 00:00

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

Posted by Community Admin on 28-Mar-2013 00:00

Hi Daniel,

Brilliant, thanks again. Got it all working. Took your advice and used a Repeater. :-)

Posted by Community Admin on 28-Mar-2013 00:00

Okay, great!

Kind regards,
Daniel

This thread is closed