2009
09.03

Para aqueles que não conhecem o Kentico CMS, aconselho a darem uma olhadela à homepage deles, considero-o um bom CMS ( tendo em conta aquilo com que já trabalhei, Joomla e Mambo, que para mim são péssimos… )…

Têm várias versões de licenciamento do software, mas a meu ver são bastante irreais para o mercado português, então para a comunidade freelancer ainda pior, no entanto têm uma versão free, mas que têm uma condição.. da qual eu não gosto nada, para podermos usar a versão free temos de por o “branding” deles em todas as páginas que são geridas pelo CMS, não acredito que seja fácil vender isto a um cliente…

Mas no final, considero que é um excelente CMS, e na última versão que testei ( versão 4.0 ), está mesmo muito bom… já saiu a versão 4.1 ( no mês passado senão estou em erro )…

Mas voltando ao que me fez criar um post..

Ontem e hoje, estive à luta com um CMS:Repeater ( controlo do Kentico, basicamente fizeram um “extend” ao Repeater do .Net ) e com o CMS:TemplateDataPager…

Já tinha usado esta combinação 2 dias antes, e não tive problemas, só que tinha usado através de webpart’s clonadas ( clonei a webpart do Kentico CMS:Repeater ), desliguei o DataBindingByDefault e o EnablePagging do CMS:Repeater e problema resolvido, foi só afectar o TemplateDataPager com o DataSource do CMS:Repeater e problema resolvido…

Vendo o exemplo deles, é bastante fácil de o fazer:

Página:

<table style="border: solid 1px #CCCCCC; margin-left: auto; margin-right: auto;">
    <tr>
        <td style="border-bottom: solid 1px #CCCCCC; padding: 10px; text-align: center;">
            <cc1:cmsrepeater id="CMSRepeater1" runat="server" path="/%" classnames="CMS.Product"
                transformationname="CMS.Product.preview">
            </cc1:cmsrepeater>
        </td>
    </tr>
    <tr>
        <td style="padding: 10px; background-color: #D9D9D9;">
            <cc1:templatedatapager id="TemplateDataPager1" runat="server">
                <NumberTemplate>
                    <a href="?Page=<%# Eval("PageNumber")  %>"><%# Eval("PageNumber")  %></a>
                </NumberTemplate>
                <SelectedNumberTemplate>
                    <b><%# Eval("PageNumber")  %></b>
                </SelectedNumberTemplate>
                <SeparatorTemplate>
                    -
                </SeparatorTemplate>
                <FirstItemTemplate>
                    <a href="?Page=1">First</a>&nbsp;|&nbsp;
                </FirstItemTemplate>
                <LastItemTemplate>
                    &nbsp;|&nbsp;<a href="?Page=<%# pageCount %>">Last</a>
                </LastItemTemplate>
                <PreviousItemTemplate>
                    <a href="?Page=<%# previousPage %>">Previous</a> &nbsp;|&nbsp;
                </PreviousItemTemplate>
                <NextItemTemplate>
                    &nbsp;|&nbsp; <a href="?Page=<%# nextPage %>">Next</a>
                </NextItemTemplate>
            </cc1:templatedatapager>
        </td>
    </tr>
</table>

Code behind:

using CMS.GlobalHelper;
public partial class CMSControlsExamples_TemplatedDataPager : ControlsExamplesPage
{
    public string pageCount = "1";
    public string previousPage = "1";
    public string nextPage = "";

    ///
    /// OnInit override
    ///
    ///
    protected override void OnInit(EventArgs e)
    {
        // Disable repeater pager and databindbydefault
        CMSRepeater1.EnablePaging = false;
        CMSRepeater1.DataBindByDefault = false;
        base.OnInit(e);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // Get repeater datasource
        TemplateDataPager1.DataSource = CMSRepeater1.DataSource;
        // Set page size
        TemplateDataPager1.PageSize = 1;
        // Set current page from query string
        TemplateDataPager1.CurrentPage = ValidationHelper.GetInteger(Request.QueryString["Page"], 1);
        // Get page number for last link
        pageCount = ((int)(TemplateDataPager1.PageCount - 1)).ToString();
        // Set default next page link
        nextPage = pageCount;
        // Set previous link
        if ((TemplateDataPager1.CurrentPage - 1) >= 1)
        {
            previousPage = ((int)(TemplateDataPager1.CurrentPage - 1)).ToString();
        }
        // Set next link
        if ((TemplateDataPager1.CurrentPage + 1) <= (TemplateDataPager1.PageCount - 1))
        {
            nextPage = ((int)(TemplateDataPager1.CurrentPage + 1)).ToString();
        }
        // Set paged datasource to the repeater and databind it
        CMSRepeater1.DataSource = TemplateDataPager1.PagedData;
        if (!DataHelper.DataSourceIsEmpty(CMSRepeater1.DataSource))
        {
            CMSRepeater1.DataBind();
        }
    }
}

Até aqui sem problemas, consegui-o usar sem acontecer nada, o problema surgiu foi quando tentei afectar o CMS:Repeater com um DataSource vindo de uma query, tentei de várias maneiras afectar o DataSource do CMS:TemplateDataPager, que o DataSource ficava sempre a vazio, apesar de a query estar a retornar 38000 resultados.

Estava a usar mais ou menos este código ( na realidade tenho as chamadas à base de dados encapsuladas com tratamento de excepções):

protected void Page_Load(object sender, EventArgs e)
{
    GeneralConnection cn = new GeneralConnection();
    DataSet ds = null;
    object[,] parameters = new object[1, 3];
    parameters[0, 0] = "@UserName";
    parameters[0, 1] = "johns";
    CMSRepeater1.DataSource = cn.ExecuteQuery("cms.user.selectbyname", parameters).Tables[0];
    // Get repeater datasource
    TemplateDataPager1.DataSource = CMSRepeater1.DataSource;
    // Set page size
    TemplateDataPager1.PageSize = 1;
    // Set current page from query string
    TemplateDataPager1.CurrentPage = ValidationHelper.GetInteger(Request.QueryString["Page"], 1);
    // Get page number for last link
    pageCount = ((int)(TemplateDataPager1.PageCount - 1)).ToString();
    // Set default next page link
    nextPage = pageCount;
    // Set previous link
    if ((TemplateDataPager1.CurrentPage - 1) >= 1)
    {
        previousPage = ((int)(TemplateDataPager1.CurrentPage - 1)).ToString();
    }
    // Set next link
    if ((TemplateDataPager1.CurrentPage + 1) <= (TemplateDataPager1.PageCount - 1))
    {
        nextPage = ((int)(TemplateDataPager1.CurrentPage + 1)).ToString();
    }
    // Set paged datasource to the repeater and databind it
    CMSRepeater1.DataSource = TemplateDataPager1.PagedData;
    if (!DataHelper.DataSourceIsEmpty(CMSRepeater1.DataSource))
    {
        CMSRepeater1.DataBind();
    }
}

Este código não faz absolutamente nada, ou melhor até faz, a query à base de dados é efectuada correctamente, retorna resultados, só que quando se afecta a DataSource do TemplateDataPager, esta ficava sempre a null…

E qual era o problema, é que pelos vistos quando afectava a DataSource do CMS:Repeater, a DataSource ficava com o tipo DataTable, até aqui tudo bem, se eu comentasse o CMS:TemplateDataPager, o CMS:Repeater era preenchido, o transform efectuado e tudo aparecia às mil maravilhas..

O que acontece é que o DataSource do CMS:TemplateDataPager tem de ser um DataView, em vez do DataTable..coisa simples não é?

Clonando a webpart deles, nunca afectamos directamente o DataSource do CMS:Repeater, este é afectado por eles, e o DataSource fica sempre com DataView, quer seja um CMS:Queryrepeater, quer seja um CMS:Repeater… por isso é que o erro não foi detectado nas webpart’s que tinha clonado anteriormente…

Após ter alterado o código para:

protected void Page_Load(object sender, EventArgs e)
{
    GeneralConnection cn = new GeneralConnection();
    DataSet ds = null;
    object[,] parameters = new object[1, 3];
    parameters[0, 0] = "@UserName";
    parameters[0, 1] = "johns";
    CMSRepeater1.DataSource = cn.ExecuteQuery("cms.user.selectbyname", parameters).Tables[0].DefaultView;
    // Get repeater datasource
    TemplateDataPager1.DataSource = CMSRepeater1.DataSource;
    // Set page size
    TemplateDataPager1.PageSize = 1;
    // Set current page from query string
    TemplateDataPager1.CurrentPage = ValidationHelper.GetInteger(Request.QueryString["Page"], 1);
    // Get page number for last link
    pageCount = ((int)(TemplateDataPager1.PageCount - 1)).ToString();
    // Set default next page link
    nextPage = pageCount;
    // Set previous link
    if ((TemplateDataPager1.CurrentPage - 1) >= 1)
    {
        previousPage = ((int)(TemplateDataPager1.CurrentPage - 1)).ToString();
    }
    // Set next link
    if ((TemplateDataPager1.CurrentPage + 1) <= (TemplateDataPager1.PageCount - 1))
    {
        nextPage = ((int)(TemplateDataPager1.CurrentPage + 1)).ToString();
    }
    // Set paged datasource to the repeater and databind it
    CMSRepeater1.DataSource = TemplateDataPager1.PagedData;
    if (!DataHelper.DataSourceIsEmpty(CMSRepeater1.DataSource))
    {
        CMSRepeater1.DataBind();
    }
}

Ficou tudo a funcionar às mil maravilhas..

Nem imaginam as voltas que dei para encontrar esta solução, estava difícil mas consegui..

Um bem haja a todos e bom código..

No Comment.

Add Your Comment