Pergunta

I am using a SelectMethod for GridView, I use ModelBnding. The simplified view:

<asp:GridView AllowPaging="True" 
        AllowSorting="True"
        runat="server"
        PageSize="10" 
        SelectMethod="GetRedirections"
        ID="rediretionGrid" AutoGenerateColumns="False" 
        ItemType="TTC.TT.Entities.ViewModels.Redirections.RedirectionView"
        DataKeyNames="Id"
        >
...
</asp:GridView>

The code behind:

public IQueryable<RedirectionView> GetRedirections2([Control] string filter)
{
    var mappings = RedirectionService.GetRedirections().Where(x => x.Source.Contains(filter)).AsQueryable();

    // Setting PageIndex to 0 doesn't solve the problem.
    rediretionGrid.PageIndex = 0;
    return mappings;
}

When filter is set to something popular multiple results are returned (for example 2000) user is able to go to different pagination page (for example he will go to page 30) unfortunately when he changes the filter to something not popular and not as many results are returned (for example 3 results) DataGrid will display information that 'No items were found' because DataGrid preserves the information that the user was on a far away page (30) and he is trying to display that page with a respect to new filtering. Everything is working if a user is on a first page. What is a work around? How can I either send a user to a first page (or any other page that will display results, typically it is last page) when a filter is changed, or do something to avoid a situation when DataGrid is not showing anything even when multiple records were found.

My experiments with PageIndex to 0 don't solve the problem (they introduce more issues, but I just want to mention it, in case anyone suggests this answer). When I set PageIndex to 0, still DataGrid is not showing any result.

To make it clear, I know how can I resolve this issue, but the implementation is long, and I can't believe that M$ could potentially not see this happening. Because if I am forced to implement additional event listeners and add a custom logic to handle this situation for me using ModelBinding with SelectMethod is pointless, it is not worth it, because writing this custom logic takes more time, then not using SelectMethod and ModelBinding.

Update: Simple experiment with return type for SelectMethod showed that when I change a definition of my GetRedirection2 method to:

public IEnumerable<RedirectionView> GetRedirections2(int maximumRows, int startRowIndex, out int totalRowCount, string sortByExpression, [Control] string filter)

And I do pagination and sorting on my own, and I try to set PageIndex to 0 like:

if (startRowIndex > totalRowCount)
{
    rediretionGrid.PageIndex = 0;
}

Setting it now doesn't resolves the issue because it is already too late to do it. I believe that DataGrid still stores it's startRowIndex and uses it to handle data after it was returned. And at the very end it uses PageIndex and pretends to display page 0, when really it displayed different page. So the thing I would like to have is a method to change startRowIndex like having a parameter marked as out just like totalRowCount is handled.

Foi útil?

Solução

The simplest and quickest to implement way I was able to come up, but also a terrible way in terms of what I would like to see is to do a full page reload. So, I returned to my original GetRedirections2 method definition. Code below is simplified for visibility reasons:

public IQueryable<RedirectionView> GetRedirections2([Control] string filter)
{
    var mappings = RedirectionService.GetRedirections().Where(x => x.Source.Contains(filter));

    // This is a terrible hack to redirect user to a first page.
    if (rediretionGrid.PageIndex * rediretionGrid.PageSize > mappings.Count)
    {
        Response.Redirect(Paths.Redirections.Index_aspx + "?filterValue=" + filter);
    }
    return mappings.AsQueryable();
}

And in Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) return;
    var filterValue = Request.QueryString["filterValue"];
    filter.Text = filterValue;
}

I wish there was a proper way of doing it, w/o a need of implementing hacks like this :(

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top