1

我有一个使用 EF 的 MVC 项目,其中包含许多项目(名称、描述、截止日期等)。它们还具有某些事物,例如与它们相关联的区域及其活动状态(进行中、非活动等)。我想要做的是通过部分视图使用 Telerik 下拉列表从这些中过滤。我还尝试在更改时将过滤器的最后状态保存在 cookie 中。

我遇到的问题是,当我更改过滤器时,更改事件并不总是被调用。

该索引用于加载其中包含的应用程序的外壳。

  1. Telerik 下拉菜单是使用带有 on-change 事件的 Viewbag 创建的
  2. 为局部视图加载项目
  3. 在顶部为有关项目的其他网页生成导航菜单

在页面加载的第一个实例中读取 cookie 状态。

        [HttpGet]
        public ActionResult Index()
        {

            int Region_ID = -1;
            int State_ID = -1;

            if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("Cookie"))
            {
                List<string> str = this.ControllerContext.HttpContext.Request.Cookies["Cookie"].Value.Split(',').ToList<string>();
                Region_ID = Convert.ToInt32(str[0]);
                State_ID  = Convert.ToInt32(str[1]);

            }

            db = new DashboardEntities();
            var filterRegion = new SelectList(db.Region.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name",Region_ID).ToList();
            var filterState = new SelectList(db.State.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name",State_ID).ToList();


            filterRegion.Insert(0, new SelectListItem { Text = "All", Value = "-1" });
            filterState.Insert(0, new SelectListItem { Text = "All", Value = "-1" });

            ViewBag.FilterRegionSelectList = filterRegion;
            ViewBag.FilterStateSelectList = filterState;

            var prj = (db.Project.Include("Builder").Include("ProjectNotes").Where(m => m.Builder.Region_ID == Region_ID || Region_ID == -1)
                      .Where(m => m.State_ID == State_ID || State_ID == -1)

            return View(prj);
        }

部分用于在首次加载页面后显示过滤器更改。此外,当过滤器更改时,cookie 会在重新加载正确的项目集合时在此处更新。

    public PartialViewResult DashboardPartial(int id, int state )
    {
        db = new DashboardEntities();

        var filterRegion = new SelectList(db.Region.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name", id).ToList();
        var filterState = new SelectList(db.State.Where(m => m.Active).OrderBy(n => n.Name), "ID", "Name", state).ToList();


        filterRegion.Insert(0, new SelectListItem { Text = "All", Value = "-1" });
        filterState.Insert(0, new SelectListItem { Text = "All", Value = "-1" });


        ViewBag.FilterRegionSelectList = filterRegion;
        ViewBag.FilterStateSelectList = filterState;


        HttpCookie cookie = new HttpCookie("Cookie");
        cookie.Value = id.ToString() + "," + state.ToString() ;
        this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);

        var prj = db.Project.Include("Builder").Include("ProjectNotes").Where(m => m.Builder.Region_ID == id || id == -1)
                  .Where(m => m.State_ID == state || state == -1);

        ViewBag.Model = prj;

        return PartialView(prj);
    }

该视图包含一些 javascript 来处理更改事件。我通过将 Telerik 下拉列表的 on-change 事件设置为 filterChange() 函数来做到这一点。

@using Dashboard.Helpers

@{
    ViewBag.Title = "Dashboard";
}


<script type="text/javascript">

    function filterChange() {
        $("#log").ajaxError(function (event, jqxhr, settings, exception) {
            alert(exception);
        });

        var regionValue = $('#filterRegion').data('tDropDownList').value();
        var stateValue = $('#filterState').data('tDropDownList').value();


        //alert('Index: ' + regionValue.toString() + ',' + stateValue.toString());


        $.get('@Url.Action("DashboardPartial")',
        { id: regionValue.toString(), state: stateValue.toString() }, function (data) {
            $("#target").html(data);
        });

    }
</script>

<div style="width: 100%; height: 100%">
    <fieldset>     
        <legend>Filters</legend>
        <div>
            @using (Html.BeginForm())
            {
            <div class="Filter-Div">
                <div style="float: left;">
                    @Html.Label("Region:")
                </div>
                <div style="float: left;">
                    @Html.Telerik().DropDownList().Name("filterRegion").BindTo((List<SelectListItem>)@ViewBag.FilterRegionSelectList).ClientEvents(events => events.OnChange("filterChange"))
                </div>
            </div>
            <div class="Filter-Div">
                <div style="float: left;">
                    @Html.Label("Project State:")
                </div>
                <div style="float: left;">
                    @Html.Telerik().DropDownList().Name("filterState").BindTo((List<SelectListItem>)@ViewBag.FilterStateSelectList).ClientEvents(events => events.OnChange("filterChange"))
                </div>
            </div>

            <div class="Filter-Div">
                <table class="noborder">
                    <tr class="noborder"> <input type="submit" value="Export" name="btnName" /> </tr>   
                </table>
            </div>
            }

        </div>
    </fieldset>  
    @(Html.Telerik().ScriptRegistrar()
    .DefaultGroup(group => group
                .Add("telerik.common.js")
                .Add("telerik.tabstrip.min.js")
                .Add("telerik.calendar.min.js"))
    .jQuery(false))  
    <div>
     @if (User.IsInRole("SuperUser") || User.IsInRole("Admin"))
     {   
        @Html.ActionLink("Create New", "Create", new { controller = "Dashboard", page = "Index" }, new { @class = "t-button" })
     }
    </div>
</div>

<div id="target">
   @{ Html.RenderPartial("DashboardPartial"); 

   }
</div>

请注意,我是 MVC 和实体框架的新手,因此如果您看到无论如何改进代码的方法。感谢您提供任何帮助。

旁注 - 我目前正在实现项目的 Viewmodel 表示,而不是将 EF 直接传递给 View。

4

1 回答 1

1

我解决了这个问题。

问题在于,默认情况下,部分视图正在为该会话中生成的所有部分视图结果缓存。因此,每次更改过滤器时都不会发回部分操作。我能够使用部分操作的 OutputCache HTML 属性将缓存限制到更合适的时间长度。

[OutputCache(Duration=(number of seconds))] 
于 2013-07-09T17:48:58.700 回答