Skip to content

Commit 4503361

Browse files
authored
feature: DataGrid Columns allow Sort and Filter when bound to Array<o… (#2233)
* feature: DataGrid Columns allow Sort and Filter when bound to Array<object>[] i.e. DataRow.ItemArray[n] * Expose Test page and fix AmbiguousMatch in test (ItemArray not Item) * Working filters before test * In Sorting Tests * Filter by ChecBoxList to be done * Better solution to filter types * Solution for Enum in DataTable * Tidy up and fix of Enum Null Working Enums * Re-enabled all data sources in tests * Prevent display of simple filter input when fitler expects enumerable Show correct demo code, only when merged with Master * Fix to handle Filter lists with nullable enums
1 parent f2bc7ef commit 4503361

16 files changed

+1706
-21
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
using Bunit;
2+
using Microsoft.AspNetCore.Components;
3+
using Microsoft.AspNetCore.Components.Rendering;
4+
using Microsoft.Extensions.Options;
5+
using System;
6+
using System.Collections;
7+
using System.Collections.Generic;
8+
using System.ComponentModel;
9+
using System.Data;
10+
using System.Data.Common;
11+
using System.IO;
12+
using System.Linq;
13+
using System.Linq.Expressions;
14+
using System.Reflection;
15+
using System.Text;
16+
using System.Text.Json;
17+
using System.Text.Json.Serialization;
18+
using System.Threading.Tasks;
19+
using Xunit;
20+
21+
namespace Radzen.Blazor.Tests.Integration
22+
{
23+
public static class DataFixtureHelpers
24+
{
25+
public const int Rows = 9;
26+
public const int Cols = 6;
27+
public static IRenderedComponent<RadzenDataGrid<T>> GetTestDataGridIncCols<T>(this IEnumerable<T> data, TestContext ctx)
28+
{
29+
var component = ctx.RenderComponent<RadzenDataGrid<T>>(parameterBuilder =>
30+
{
31+
parameterBuilder.Add<IEnumerable<T>>(p => p.Data, data);
32+
parameterBuilder.Add<bool>(p => p.AllowFiltering, true);
33+
parameterBuilder.Add<bool>(p => p.AllowSorting, true);
34+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.EmployeeID), data));
35+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.FirstName), data));
36+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.LastName), data));
37+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.TitleOfCourtesy), data));
38+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.Title), data));
39+
parameterBuilder.Add<RenderFragment>(p => p.Columns, b => columnBuilder<T>(b, nameof(Employee.HireDate), data));
40+
41+
});
42+
43+
var dg = component.Instance;
44+
var cols = dg.ColumnsCollection.Count;
45+
var rows = dg.Data.Count();
46+
Assert.Equal(Cols, cols);
47+
Assert.Equal(Rows, rows);
48+
return component;
49+
}
50+
public static IRenderedComponent<RadzenDataGrid<T>> GetTestDataGrid<T>(this IEnumerable<T> data, TestContext ctx)
51+
{
52+
var component = ctx.RenderComponent<RadzenDataGrid<T>>(parameterBuilder =>
53+
{
54+
parameterBuilder.Add<IEnumerable<T>>(p => p.Data, data);
55+
parameterBuilder.Add<bool>(p => p.AllowFiltering, true);
56+
parameterBuilder.Add<bool>(p => p.AllowSorting, true);
57+
});
58+
59+
var dg = component.Instance;
60+
var cols = dg.ColumnsCollection.Count;
61+
var rows = dg.Data.Count();
62+
Assert.Equal(0, cols);
63+
Assert.Equal(Rows, rows);
64+
return component;
65+
}
66+
67+
68+
public static RenderTreeBuilder columnBuilder<T>(this RenderTreeBuilder b, string property, IEnumerable<T> data, bool sortable = true, bool filterable = true, FilterMode? filterMode = null, object filterValue = null)
69+
{
70+
int sequ = 0;
71+
if (data is IEnumerable<DataRow> rows)
72+
{
73+
Assert.NotEmpty(rows);
74+
var table = (data.First() as DataRow).Table;
75+
Assert.NotNull(table);
76+
DataColumn dataCol = table.Columns[property];
77+
Assert.NotNull(dataCol);
78+
b.OpenComponent(sequ++, typeof(RadzenDataGridColumn<T>));
79+
b.AddAttribute(sequ++, "Title", dataCol.ColumnName);
80+
b.AddAttribute(sequ++, "Property", $"ItemArray[{dataCol.Table.Columns.IndexOf(dataCol)}]");
81+
b.AddAttribute(sequ++, "Type", dataCol.DataColType());
82+
}
83+
else
84+
{
85+
b.OpenComponent(sequ++, typeof(RadzenDataGridColumn<T>));
86+
b.AddAttribute(sequ++, "Title", property);
87+
b.AddAttribute(sequ++, "Property", property);
88+
}
89+
90+
b.AddAttribute(sequ++, "Sortable", sortable);
91+
b.AddAttribute(sequ++, "Filterable", filterable);
92+
if (filterMode != null) b.AddAttribute(sequ++, "FilterMode", filterMode);
93+
if (filterValue != null) b.AddAttribute(sequ++, "FilterValue", filterValue);
94+
b.CloseComponent();
95+
return b;
96+
}
97+
98+
public static DataTable GetDataTable<T>(this IEnumerable<T> employees)
99+
{
100+
DataTable dataTable = new DataTable(typeof(T).Name);
101+
102+
PropertyInfo[] properties = typeof(T).GetProperties();
103+
foreach (PropertyInfo property in properties)
104+
{
105+
var col = new DataColumn();
106+
col.ColumnName = property.Name;
107+
col.DataType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
108+
col.AllowDBNull = Nullable.GetUnderlyingType(property.PropertyType) != null || !property.PropertyType.IsValueType;
109+
dataTable.Columns.Add(col);
110+
}
111+
foreach (T item in employees)
112+
{
113+
DataRow row = dataTable.NewRow();
114+
foreach (PropertyInfo property in properties)
115+
{
116+
row[property.Name] = property.GetValue(item, null) ?? DBNull.Value;
117+
}
118+
dataTable.Rows.Add(row);
119+
}
120+
121+
return dataTable;
122+
}
123+
124+
public static IEnumerable<T> GetEmployees<T>()
125+
{
126+
using (FileStream fs = new FileStream(@"Integration\Employees.json", FileMode.Open, FileAccess.Read))
127+
{
128+
var options = new JsonSerializerOptions
129+
{
130+
Converters =
131+
{
132+
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
133+
}
134+
};
135+
var employees = JsonSerializer.Deserialize<IEnumerable<T>>(fs, options);
136+
return employees;
137+
}
138+
}
139+
140+
public static Type DataColType(this DataColumn dataCol)
141+
{
142+
return dataCol.AllowDBNull && dataCol.DataType.IsValueType
143+
? typeof(Nullable<>).MakeGenericType(dataCol.DataType)
144+
: dataCol.DataType;
145+
}
146+
}
147+
148+
public class TestGridData : IEnumerable<object[]>
149+
{
150+
private readonly IEnumerable<object[]> _data = new List<object[]>
151+
{
152+
new object[] {DataFixtureHelpers.GetEmployees<Employee>() },
153+
new object[] {DataFixtureHelpers.GetEmployees<Employee>().AsQueryable()},
154+
new object[] {DataFixtureHelpers.GetEmployees<Employee>().AsODataEnumerable()},
155+
new object[] {DataFixtureHelpers.GetEmployees<Employee>().GetDataTable().AsEnumerable()},
156+
};
157+
158+
public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();
159+
160+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
161+
}
162+
163+
public class DataFixture
164+
{
165+
protected const int _rows = DataFixtureHelpers.Rows;
166+
protected const int _cols = DataFixtureHelpers.Cols;
167+
168+
public DataFixture()
169+
{
170+
}
171+
172+
}
173+
}

0 commit comments

Comments
 (0)