Kendo Grid动态列过滤功能失效问题咨询
Hey there, let's dig into why your ReceivedMonth column filtering isn't working and how to fix it. The core issue here is that ReceivedMonth is a calculated read-only property—it doesn't exist as a field in your database, so Kendo Grid's default server-side filtering can't automatically map it to a database query. Here are your best solutions, depending on your use case:
Option 1: Front-End Filtering (Great for Small Datasets)
If your dataset isn't huge, you can switch to client-side filtering so the grid handles filtering directly in the browser without hitting the backend for every filter change.
Step 1: Configure the Grid for Client-Side Operations
Update your Grid data source to disable server operations, and set up the filter UI for the month column:
@(Html.Kendo().Grid<YourViewModel>() .Name("receivedDataGrid") .DataSource(dataSource => dataSource .Ajax() .ServerOperation(false) // Enable client-side filtering/sorting/paging .Read(read => read.Action("YourReadAction", "YourController")) ) .Columns(columns => { columns.Bound(p => p.ReceivedDate) .Format("{0:yyyy-MM-dd}") .Filterable(filterable => filterable.UI("dateFilter")); // Optional custom date picker columns.Bound(p => p.ReceivedMonth) .Filterable(filterable => filterable .UI("monthDropdownFilter") // Custom dropdown for month selection .Operator("eq") // Use exact match for month names ); }) .Filterable() // Enable overall grid filtering )
Step 2: Add Custom Filter UI (Optional but User-Friendly)
Add a JavaScript function to render a dropdown of month names instead of the default text filter:
function monthDropdownFilter(element) { element.kendoDropDownList({ dataSource: [ { text: "January", value: "January" }, { text: "February", value: "February" }, { text: "March", value: "March" }, { text: "April", value: "April" }, { text: "May", value: "May" }, { text: "June", value: "June" }, { text: "July", value: "July" }, { text: "August", value: "August" }, { text: "September", value: "September" }, { text: "October", value: "October" }, { text: "November", value: "November" }, { text: "December", value: "December" } ], optionLabel: "--Select a Month--" }); } // Optional: Custom date filter for ReceivedDate function dateFilter(element) { element.kendoDatePicker({ format: "yyyy-MM-dd" }); }
Option 2: Server-Side Filtering (For Large Datasets)
If you need to keep server-side operations (to handle large amounts of data), you'll need to manually intercept and translate the ReceivedMonth filter into a database-friendly query using the underlying ReceivedDate field.
Step 1: Adjust Your Backend Read Action
Modify your controller's read method to parse the ReceivedMonth filter and convert it into a filter on the ReceivedDate month:
using System.Globalization; using Kendo.Mvc.Extensions; using Kendo.Mvc.UI; public ActionResult Read([DataSourceRequest] DataSourceRequest request) { // Start with your base query mapping entities to ViewModel var query = _dbContext.YourEntities .Select(e => new YourViewModel { ReceivedDate = e.ReceivedDate, // Map other properties here }); // Check if there's a filter for ReceivedMonth var monthFilter = request.Filters .OfType<FilterDescriptor>() .FirstOrDefault(f => f.Member == "ReceivedMonth"); if (monthFilter != null && monthFilter.Value != null) { // Convert the month name (e.g., "January") to its numeric value (1) var targetMonthName = monthFilter.Value.ToString(); int targetMonthNumber = DateTime.ParseExact( targetMonthName, "MMMM", CultureInfo.InvariantCulture ).Month; // Filter the query by ReceivedDate's month query = query.Where(v => v.ReceivedDate.HasValue && v.ReceivedDate.Value.Month == targetMonthNumber); // Remove the original filter to prevent Kendo from trying to process it (it'll fail otherwise) request.Filters.Remove(monthFilter); } // Apply remaining filters/sorting/paging and return the result var result = query.ToDataSourceResult(request); return Json(result, JsonRequestBehavior.AllowGet); }
Step 2: Keep Your Grid Configuration
Your existing Grid setup can stay mostly the same—just ensure server operations are enabled (which they are by default for Ajax data sources):
columns.Bound(p => p.ReceivedMonth) .Filterable(filterable => filterable .Operator("eq") // Exact match for month names );
Option 3: Use EF Core Calculated Columns (Alternative Server-Side Approach)
If you're using EF Core, you can project the ReceivedMonth directly in your query using database functions, so EF can translate it to SQL and support automatic server-side filtering.
Example Query with EF Core Date Functions
var query = _dbContext.YourEntities .Select(e => new YourViewModel { ReceivedDate = e.ReceivedDate, // Use EF.Functions to get the month name directly from the database ReceivedMonth = e.ReceivedDate.HasValue ? EF.Functions.DateName("month", e.ReceivedDate) : string.Empty, // Map other properties }); // Let Kendo handle the rest—no manual filter parsing needed! var result = query.ToDataSourceResult(request); return Json(result, JsonRequestBehavior.AllowGet);
This works because EF.Functions.DateName translates to SQL's DATENAME function, so the database calculates the month name, and Kendo can filter it like any other field.
内容的提问来源于stack exchange,提问作者Rich

