November Happy Hour will be moved to Thursday December 5th.

Random order in PageList

Vote:
 

Hi,

I've got a PageList and I'd like to randomize the order of it. Is this done through a ForEach of some kind or is there a simpler way?

Best regards,

#35371
Dec 08, 2009 14:53
Vote:
 

Hi

Take a look at the filter event of the PageList. I would create a custom filter that randomizes the pages.

I've written a little about it:

#35381
Dec 08, 2009 15:59
Vote:
 

I've looked at it and must say that it didn't make me any wiser. I can see how I can use it to filter out things but not randomize the order of the pages it containes.

#35395
Dec 09, 2009 8:02
Vote:
 

Filter is not a very good name for what you can do with it. Think of filters more of a way to manipulate your PageDataCollection in any way you like. Remove pages, add pages, sort them, randomize, add properties to them etc.

If you take a look at my sample, you'll see that in the Filter method you have access to the whole PageDataCollection. Now you only need to loop through them and randomize :).

#35397
Dec 09, 2009 9:30
Vote:
 

I actually found this code http://world.episerver.com/Templates/Forum/Pages/Thread.aspx?id=13161&ampepslanguage=en/ showing how it's done but what I can't seem to get the hang of is how to get the content of my PageList into a PageDataCollection. Or am I not getting the picture here? :)

#35398
Edited, Dec 09, 2009 10:30
Vote:
 

No worries, we are all here to learn! Lets see, with PageList do you mean PageList.ascx (from the Public Templates) or PageList the EPiServer web control?

#35399
Dec 09, 2009 10:43
Vote:
 

I actually edited my last response while you wrote your answer... :)

I'm using a modified version of the ascx-file from the Public Templates.

#35400
Dec 09, 2009 10:47
Vote:
 

Something like this.

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    ...
    epiPageList.Filter += this.epiPageList_Filter;
    ...
}

protected void epiPageList_Filter(object sender, FilterEventArgs e)
{
    new FilterRandomPages().Filter(e.Pages);
}

#35401
Dec 09, 2009 10:59
Vote:
 

That's it! Now I get it. Actually learned something toady, too. :) Thanks!

Regarding the link to the randomscript I posted earlier; Is it just me or is that not very random? More like scrolling.

#35405
Dec 09, 2009 11:49
Vote:
 

Looks okay, but personally I prefer Linq for this :).

public static IEnumerable Randomize(this IEnumerable source)
{
    Random rnd = new Random();
    return source.OrderBy((item) => rnd.Next());
}
Now you can just do myPageDataCollection.Randomize();

#35406
Dec 09, 2009 12:07
Vote:
 

Not sure how to use that... :/

#35407
Dec 09, 2009 13:02
Vote:
 

Hi Peter

For some reason the PageDataCollection wasn't to found of the OrderBy extension method. I used the Sort method instead.

using System;
using System.Collections.Generic;
using EPiServer.Core;
using EPiServer.Filters;

namespace FV.Templates.FV.Filters
{
    public class FilterRandomize : IPageFilter
    {
        public void Filter(PageDataCollection pages)
        {
            pages.Sort(new FilterRandomizeSort());
        }

        public void Filter(object sender, FilterEventArgs e)
        {
            this.Filter(e.Pages);
        }

        public bool ShouldFilter(PageData page)
        {
            throw new NotImplementedException();
        }
    }

    public class FilterRandomizeSort : IComparer
    {
        public int Compare(PageData page1, PageData page2)
        {
            return new Random().Next();
        }
    }
}

#35412
Dec 09, 2009 20:06
Vote:
 

I feel like I'm getting a little water over my head here. When I try to implement that code I get: "Using the generic type 'System.Collections.Generic.IComparer<T>' requires '1' type arguments" on row "public class FilterRandomizeSort : IComparer".

#35418
Dec 10, 2009 8:45
Vote:
 

Could you post your code for the custom Filter and Comparer?

#35419
Dec 10, 2009 8:54
Vote:
 

Right now it looks excactly the same as the code you posted besides from the namespace.

#35420
Dec 10, 2009 9:01
Vote:
 

Sorry, client meeting.. I see the mistake now:

public class FilterRandomizeSort : IComparer

Should be:

public class FilterRandomizeSort : IComparer<PageData>

#35427
Dec 10, 2009 12:03
Vote:
 

For some reason the syntax highlighter removed <PageData> when I added the code..

#35428
Dec 10, 2009 12:04
Vote:
 

What I wanted to use this for was to randomize the order of a commercial banner listing in the right hand of the page. With the code you've so kindly composed here they randomize, but only ones. If I reload the page they remain in the same order. With the other code that I linked to further up they reorder them self every time the page is reloaded but with the downside that a couple of them nearly always to end up in the same position.

#35430
Dec 10, 2009 14:07
Vote:
 

The code you mentioned where I was able to use Linq, how is this implemented? It may sound strange but I've still got a problem with some of the items almost always showing up in the same place in the order. Here's my class so far.

public class FilterRandomize : IPageFilter

{

public void Filter(PageDataCollection pages)

{

for (int i = 0; i < pages.Count; i++)

{

PageData x = pages[i];

Random rng = new Random();

int index = rng.Next(pages.Count - i) + i;

pages[i] = pages[index];

pages[index] = x;

}

}

 

public void Filter(object sender, FilterEventArgs e)

{

this.Filter(e.Pages);

}

 

public bool ShouldFilter(PageData page)

{

throw new NotImplementedException();

}

}

#35525
Dec 15, 2009 7:59
Vote:
 

I think initializing the Random class inside a loop is a bad idé, it might get the same seed many times.

Try instantiation of the random object before the loop instead of inside.

#35528
Edited, Dec 15, 2009 9:20
Vote:
 

Of course! That solved it. Thanks to both of you for the help!

#35564
Dec 15, 2009 16:43
Vote:
 


@Frederik Vig 'For some reason the PageDataCollection wasn't to found of the OrderBy extension method'
> Import the Extension's with  using directive
using System.Linq.Expressions;
and you're good to go.

Order by Guid

Using the neat trick of ordering by a Guid
 yields the same distribution spread as the Fisher-Yates Shuffle Algorithm. The distribution spread is the ratio of the possible outcomes to the actual permutations (how many possible combinations exists versus how many the random sort can make)
For more info se the following link :http://blog.linqexchange.com/index.php/how-to-randomly-reorder-a-list-with-linq/

Armed with OrderBy Extensions and the order by Guid-trick
I propose the following solution:

//Hook up the event
yourOwn_PageList.Filter += new FilterEventHandler(YourOwn_PageList_Filter);


//Sort / filter in a random fashion
void YourOwn_PageList_Filter(object sender, EPiServer.Filters.FilterEventArgs e)
{            
            var pages = e.Pages.OrderBy(p => Guid.NewGuid()).ToArray();
            for (int i = 0; i < pages.Length; i++)
                e.Pages[i] = pages[i];                
}
    

 

 

 

 

 

 

 

#46721
Dec 30, 2010 16:17
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.