@@ -196,37 +196,28 @@ For an example with the CheckboxList Filter, see the [Custom Data]({%slug grid-c
196196```` CSHTML
197197@using Telerik.DataSource
198198
199- This custom filter menu lets you choose more than one option to match against the data source
200-
201- <TelerikGrid Data=@GridData FilterMode="@GridFilterMode.FilterMenu "
202- Height="400px" Width="600px" Pageable="true ">
199+ <TelerikGrid Data="@GridData"
200+ FilterMode="@GridFilterMode.FilterMenu"
201+ Pageable="true "
202+ Width="600px">
203203 <GridColumns>
204- <GridColumn Field="Id" Filterable="false" Width="80px" />
205-
206- <GridColumn Field="Size">
204+ <GridColumn Field="@(nameof(Product.Name))" Title="Product" Filterable="false" />
205+ <GridColumn Field="@(nameof(Product.Size))">
207206 <FilterMenuTemplate>
208- @{
209- // we store a reference to the filter context to use in the business logic to show we can
210- // we could, alternatively pass it as an argument to the event handler in the lambda expression
211- // which can be useful if you want to use the same filter for several columns
212- // you could then pass more arguments to the business logic such as field name and so on
213- theFilterContext = context;
214- }
215-
216207 @foreach (var size in Sizes)
217208 {
218209 <div>
219210 <TelerikCheckBox Value="@(IsCheckboxInCurrentFilter(context.FilterDescriptor, size))"
220211 TValue="bool"
221- ValueChanged="@((value) => UpdateCheckedSizes(value, size))"
212+ ValueChanged="@((value) => UpdateCheckedSizes(value, size, context ))"
222213 Id="@($"size_{size}")">
223214 </TelerikCheckBox>
224215 <label for="@($"size_{size}")">
225216 @if (size == null) // part of handling nulls - show meaningful text for the end user
226217 {
227218 <text>Empty</text>
228219 }
229- else
220+ else
230221 {
231222 @size
232223 }
@@ -235,16 +226,11 @@ This custom filter menu lets you choose more than one option to match against th
235226 }
236227 </FilterMenuTemplate>
237228 </GridColumn>
238-
239- <GridColumn Field="ProductName" Title="Product" Filterable="false" />
240229 </GridColumns>
241230</TelerikGrid>
242231
243232@code {
244- FilterMenuTemplateContext theFilterContext { get; set; }
245- public List<string> CheckedSizes { get; set; } = new List<string>();
246-
247- public bool IsCheckboxInCurrentFilter(CompositeFilterDescriptor filterDescriptor, string size)
233+ private bool IsCheckboxInCurrentFilter(CompositeFilterDescriptor filterDescriptor, string size)
248234 {
249235 // get all current filter descriptors and evaluate whether to select the current checkbox
250236 // the default value for string filter descriptors is null so it would select the null checkbox always
@@ -253,7 +239,7 @@ This custom filter menu lets you choose more than one option to match against th
253239 {
254240 foreach (FilterDescriptor item in filterDescriptor.FilterDescriptors)
255241 {
256- if(item.Operator == FilterOperator.IsNull)
242+ if (item.Operator == FilterOperator.IsNull)
257243 {
258244 return true;
259245 }
@@ -263,71 +249,63 @@ This custom filter menu lets you choose more than one option to match against th
263249 return filterDescriptor.FilterDescriptors.Select(f => (f as FilterDescriptor).Value?.ToString()).ToList().Contains(size);
264250 }
265251
266- public void UpdateCheckedSizes(bool value , string itemValue)
252+ private void UpdateCheckedSizes(bool isChecked , string itemValue, FilterMenuTemplateContext context )
267253 {
268- // update the list of items we want to filter by
269- var isSizeChecked = CheckedSizes.Contains(itemValue);
270- if (value && !isSizeChecked)
271- {
272- CheckedSizes.Add(itemValue);
273- }
254+ var compositeFilterDescriptor = context.FilterDescriptor;
255+ compositeFilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
274256
275- if (!value && isSizeChecked )
257+ if (!isChecked )
276258 {
277- CheckedSizes.Remove(itemValue);
278- }
279-
280- // prepare filter descriptor
281- var filterDescriptor = theFilterContext.FilterDescriptor;
282-
283- filterDescriptor.FilterDescriptors.Clear();
284- // use the OR logical operator so we include all possible values
285- filterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
286- CheckedSizes.ForEach(s => {
287- // instantiate a filter descriptor for the desired field, and with the desired operator and value
288- FilterDescriptor fd = new FilterDescriptor("Size", FilterOperator.IsEqualTo, s);
289- // set its type to the field type you filter (the Size field in this example)
290- fd.MemberType = typeof(string);
291- // handle null values - use a specific filter operator that the user cannot select on their own
292- // in this custom filter template (the grid has it in a dropdown by default)
293- if(s == null)
259+ // find and remove the filter descriptor for this checkbox
260+ compositeFilterDescriptor.FilterDescriptors.Remove(compositeFilterDescriptor.FilterDescriptors.First(x =>
294261 {
295- fd.Operator = FilterOperator.IsNull;
296- }
297-
298- filterDescriptor.FilterDescriptors.Add(fd);
299- });
300-
301- //ensure there is at least one blank filter to avoid null reference exceptions
302- if (!filterDescriptor.FilterDescriptors.Any())
262+ var fd = x as FilterDescriptor;
263+ if ((fd.Operator == FilterOperator.IsNull && itemValue == null) ||
264+ (fd.Operator == FilterOperator.IsEqualTo && fd.Value?.ToString() == itemValue))
265+ {
266+ return true;
267+ }
268+ else
269+ {
270+ return false;
271+ }
272+ }));
273+ }
274+ else
303275 {
304- filterDescriptor.FilterDescriptors.Add(new FilterDescriptor());
276+ // add a filter descriptor for this checkbox
277+ compositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
278+ {
279+ Member = nameof(Product.Size),
280+ MemberType = typeof(string),
281+ Operator = itemValue == null ? FilterOperator.IsNull : FilterOperator.IsEqualTo,
282+ Value = itemValue
283+ });
305284 }
306285 }
307286
308- // sample grid data
287+ private List<Product> GridData { get; set; }
309288
310- public List<SampleData> GridData { get; set; }
289+ private string[] Sizes = new string[] { "XS", "S", "M", "L", "XL", null };
311290
312291 protected override void OnInitialized()
313292 {
314- GridData = Enumerable.Range(1, 70).Select(x => new SampleData
293+ GridData = Enumerable.Range(1, 70).Select(x => new Product
315294 {
316295 Id = x,
317296 Size = Sizes[x % Sizes.Length],
318- ProductName = $"Product {x}"
297+ Name = $"Product {x}"
319298 }).ToList();
299+
320300 base.OnInitialized();
321301 }
322302
323- public class SampleData
303+ public class Product
324304 {
325305 public int Id { get; set; }
306+ public string Name { get; set; }
326307 public string Size { get; set; }
327- public string ProductName { get; set; }
328308 }
329-
330- public string[] Sizes = new string[] { "XS", "S", "M", "L", "XL", null };
331309}
332310````
333311
0 commit comments