2

我有一个视图,它显示搜索结果并在分页列表中排序。我将列标题添加为链接,以使用户能够以这种方式基于列进行排序:

<tr>
    <th>           
        @Html.ActionLink("Reference No", "Index", 
          new { sortOrder = ViewBag.RefNoSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    <th>
        @Html.ActionLink("Category", "Index", 
          new { sortOrder = ViewBag.CatSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    ... Some other columns
</tr>

我还以这种方式添加了寻呼机:

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index",
    new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

我使用的动作如下所示:

private Registry_fssEntities db = new Registry_fssEntities();
public ActionResult Index(string sortOrder, SearchTransacModel searchModel, SearchTransacModel currentFilter, int? page)
{            
    var model = from c in db.TRANSACs
                select c;
    ViewBag.CurrentSort = sortOrder;
    ViewBag.DispDateSortParm = String.IsNullOrEmpty(sortOrder) ? "DispDate" : "";
    ViewBag.RefNoSortParm = sortOrder == "RefNo" ? "RefNo_desc" : "RefNo";
    ViewBag.CatSortParm = sortOrder == "Cat" ? "Cat_desc" : "Cat";   
    if (searchModel.DATEDISPFROM != null || searchModel.DATEDISPTO != null || searchModel.DATEDISPFROM != null || searchModel.OFFICERNAME != null || searchModel.APPNAME != null || searchModel.REFNO != null || searchModel.PROCNAME != null)
    {
        page = 1;
    }
    else
    {
        searchModel = currentFilter;
    }
    if (searchModel != null)
    {
        if (!String.IsNullOrEmpty(searchModel.DATEDISPFROM))
        {                    
            ViewBag.DispFrom = searchModel.DATEDISPFROM.ToString();
        }
        else
        {
            searchModel.DATEDISPFROM = "01/01/" + DateTime.Today.Year.ToString();
            ViewBag.DispFrom = "01/01/" + DateTime.Today.Year.ToString();
        }
        if (!String.IsNullOrEmpty(searchModel.DATEDISPTO))
        {                   
            ViewBag.DispTo = searchModel.DATEDISPTO.ToString();
        }
        else
        {
            searchModel.DATEDISPTO = "31/12/" + DateTime.Today.Year.ToString();
            ViewBag.DispTo = "31/12/" + DateTime.Today.Year.ToString();
        }
    }
    if (searchModel != null)
    {
        var tRANSACs = new TransacBusinessLogic();
        model = tRANSACs.GetTransacs(searchModel);

        ViewBag.currentFilter = searchModel;
    }
    List<TransacViewModel> TransactionList = new List<TransacViewModel>();
    foreach (var item in model)
    {
        TransactionList.Add(new TransacViewModel {
                TRANSID = item.TRANSID,
                REFNO = item?.REFNO,
                PROCESS = item?.PROCESS,
                //CATEGORY = item.PROCESS.CATEGORY,
                DOCTYPE = item?.DOCTYPE,
                DATEDEL = returnasdate(item.DATEDEL),
                DATEDISP = returnasdate(item.DATEDISP),
                APPNAME = item?.APPNAME,
                OFFICER = item?.OFFICER,
                DATEREG = item.DATEREG
            });
    }
    switch (sortOrder)
    {
        case "DispDate":
            TransactionList = TransactionList.OrderBy(x => x.DATEDISP).ToList();
            break;
        case "RefNo":
            TransactionList = TransactionList.OrderBy(t => t.REFNO).ToList();
            break;
        case "RefNo_desc":
            TransactionList = TransactionList.OrderByDescending(t => t.PROCESS.CATEGORY.DETAIL).ToList();
            break;
        case "Cat":
            TransactionList = TransactionList.OrderBy(t => t.PROCESS.CATEGORY.DETAIL).ToList();
            break;
        case "Cat_desc":
            TransactionList = TransactionList.OrderByDescending(t => t.REFNO).ToList();
            break;
        default:
            TransactionList = TransactionList.OrderByDescending(t => t.DATEDISP).ToList();
            break;
    }
    int pageSize = 6;
    int pageNumber = (page ?? 1);            
    return View(TransactionList.ToPagedList(pageNumber, pageSize));
}

SearchTransacModel是一个模型,用于在我将搜索参数传递给控制器​​时包含它们。当我通过提交按钮提交搜索表单时它工作正常,并且我使用这样的方式将此搜索条件发送回视图ViewBagViewBag.currentFilter = searchModel;

但是,当我单击任何排序操作链接时,我会丢失搜索参数。即currentFilter当我到达控制器时为空。

我将 currentFilter 作为查询字符串传递并将搜索模型分配给它,就像在这种情况下一样:

 @Html.ActionLink("Reference No", "Index", new { sortOrder = ViewBag.RefNoSortParm, currentFilter = ViewBag.CurrentFilter })

有人可以帮忙吗?我是 MVC 的新手。

4

4 回答 4

4

您不能将视图包中的值传递回控制器。

相反,您应该在视图中使用模型绑定将信息传递给您的 post 方法。

于 2016-08-29T17:48:15.097 回答
3

您可以使用这样的操作:

public ActionResult Index(SearchModel searchModel, string sortColumn, string sortOrder)
{
    ViewBag.SearchModel = searchModel;
    ViewBag.SortColumn= sortColumn;
    ViewBag.SortOrder = sortOrder;
    var business = new BusinessLogic();
    var model = business.Search(searchModel, sortColumn, sortOrder);
    return View(model);
}

您可以通过这种方式简单地混合一些路由值。这样,搜索选项和排序选项都将在请求之间保留:

@{
    var routeValues = new RouteValueDictionary(ViewBag.SearchModel ?? new { });
    routeValues["sortColumn"] = ViewBag.SortColumn;
    routeValues["sortOrder"] = ViewBag.SortOrder;
}
@Html.ActionLink("Link Text", "Action", routeValues);

笔记:

  • 根据这个答案中的想法,您可以简单地创建一个方法,它甚至可以混合 2 个对象来为您创建路由值。

  • 您还可以将排序选项封装在一个SortOption类中,并将其ViewBag放入模型绑定中并使用它。

  • System.Linq.Dynamic将帮助您获得更动态和更干净的排序代码。

  • 要了解有关此类SearchModelBusinessLogic技术的好处的更多信息,请查看使用多个字段的过滤器/搜索 - ASP.NET MVC

  • 此要求的一个常见场景是,例如,寻呼机的页面链接或显示搜索和排序结果的网格的列链接。如果您在网格上使用此技术,分页链接应保留请求之间的搜索选项和排序选项。但是对于生成列标题链接,对于每一列,您应该使用不同的合适的排序顺序和排序列;同样对于其名称等于当前排序列的列,排序顺序应与当前排序顺序相反。列标题也应该保留页面索引。

于 2016-08-29T20:55:15.997 回答
0

从 viewbag 读取后,您可以在查询字符串中传递过滤器值。假设您的SearchTransacModel班级具有DATEDISPFROMOFFICERNAME属性,

public class SearchTransacModel
{
     public string DATEDISPFROM { set; get; }
     public string OFFICERNAME { set; get; }
}  

您可以将值作为路由值发送,其中键是属性名称(SearchTransacModel 类的),值是您拥有的值。

@{
    var filter = ViewBag.CurrentFilter as SearchTransacModel;
}
@Html.ActionLink("Reference No", "Index", new { sortOrder = ViewBag.RefNoSortParm, 
        DATEDISPFROM = filter!=null? filter.DATEDISPFROM:"", 
        OFFICERNAME = filter != null ? filter.OFFICERNAME : "" })

模型绑定器将能够将查询字符串值映射到您的currentFilter对象。

我建议您不要使用相同类型的 2 个参数(currentFilter 和 searchModel)。

于 2016-08-29T17:58:51.850 回答
0

虽然ViewBag可用于实现您正在寻找的东西,但它仍然不是为此目的而设计的。

相反,您应该创建一个模型并使用它与您的控制器和视图进行通信。

更改并调整您的回报模型,使其更大一点。

public TransactionsViewModel
{
    public SearchTransacModel SearchModel { get; set; }
    public List<TransacViewModel> TransactionList { get; set; }
}

现在您可以放弃ViewBag.currentFilter的使用并仅使用此模型。

于 2016-08-29T17:59:35.427 回答