Compare commits

...

1085 Commits

Author SHA1 Message Date
Vladimir Enchev
e47ac5b02d version updated 2022-08-11 08:20:48 +03:00
Nick Williams
9d134f8171 RadzenUpload proposed cancel functionality (#573)
* Change to DatePicker to optionally pad the time picker hour, minute or seconds components with leading zeros. Corresponding new boolean parameters are PadHours, PadMinutes and PadSeconds.

* Fixed issue with RadzenDialog where closing a nested dialog removed the 'no-scroll' class from the page body, allowing the background to scroll. The javascript 'closeDialog' function is now only invoked when the last dialog is closed.
Added a  potential impovement to RadzenDialog, whereby the dialog mask is only shown for the top most dialog, rather than the accumulative effect of multiple masks. This might be personal perference, but makes more sense to me.

* Added boolean Cancel property to UploadProgressArgs, allowing the underlying XMLHttpRequest to be aborted if required. Thereby cancelling the upload. Added boolean Cancelled property to UploadCompleteEventArgs, to determine if the request completed due to being canelled.
2022-08-11 05:54:54 +02:00
Vladimir Enchev
1ec477b5bc Catch possible exception with tooltip on dispose
Fix #572
2022-08-10 11:54:28 +02:00
Vladimir Enchev
022f203a2e Fixed DataGrid advanced filter popup when Property is not set
Fix #567
2022-08-10 09:41:58 +03:00
Vladimir Enchev
191f21bf50 DropDown aria-label fixed
Fix #566
2022-08-10 09:28:15 +03:00
Vladimir Enchev
98c4b37664 AutoComplete should open popup only on keypress not on focus 2022-08-10 09:23:46 +03:00
Atanas Korchev
2f2b40ca53 Pass the formatted text to the chart axis tick template. 2022-08-08 18:19:14 +03:00
Vladimir Enchev
8a8be30657 Version updated 2022-08-05 10:24:26 +03:00
GioeEng
0c0aafb956 fix: RadzenDropDownItem behavior on older versions of the blazor.js framework (#563) 2022-08-05 10:23:25 +03:00
Vladimir Enchev
c0bca5b923 Fixed FileInput reference not updated on Visible change 2022-08-05 10:17:02 +03:00
Vladimir Enchev
55ea356efd version updated 2022-08-04 18:16:44 +03:00
Vladimir Enchev
fbcd357b69 DropDownDataGrid string SelectedValue should not treated like IEnumerable 2022-08-04 18:16:20 +03:00
Vladimir Enchev
41db619e28 Fixed FileInput value cannot be cleared 2022-08-04 18:10:39 +03:00
Vladimir Enchev
1de8b11d75 version updated 2022-08-04 09:23:16 +03:00
Vladimir Enchev
b85f082d03 DropDownDataGrid multiple selection with LoadData improved
Fix #481
2022-08-04 09:22:37 +03:00
Vladimir Enchev
c2f08b47aa Fixed RadzenNumeric does not allow certain numbers to be entered when min and max are set 2022-08-04 08:39:51 +03:00
Vladimir Enchev
329784c9a7 DataGrid PickedColumnsChanged event added
Fix #557
2022-08-02 08:45:54 +03:00
Atanas Korchev
1d357aab0a Tooltip is not displayed for area and line series with a single value. 2022-08-01 21:51:12 +03:00
Vladimir Enchev
fe6deb559b DropDown ReadOnly property added
Fix #460
2022-08-01 15:32:21 +03:00
Vladimir Enchev
591ef4d1f9 net6.0 added to TargetFrameworks. NET5 preprocessor changed to NET5_0_OR_GREATER. 2022-08-01 14:12:45 +03:00
Vladimir Enchev
6a8a991f42 DataGrid OData demo with custom filter fixed to go to first page 2022-08-01 12:25:05 +03:00
Vladimir Enchev
87161cb97a DataGrid LoadData demo with custom filter fixed to go to first page 2022-08-01 12:21:53 +03:00
Vladimir Enchev
a28b667b38 Version updated 2022-08-01 09:48:06 +03:00
Vladimir Enchev
62c8b4b9e9 Fixed keyboard navigation for virtualized DropDownBase
Fix #556
2022-08-01 09:46:56 +03:00
GioeEng
bc0d5e2e7e feat: Dropdown disabled Items (#551)
fix: Dropdown keyboard selecting after filtering
2022-08-01 08:34:20 +03:00
Greg Horvath
a66ea60ae7 Implemented more consistent handling of DateTimeOffSet. See https://github.com/radzenhq/radzen-blazor/issues/554 (#555) 2022-08-01 08:31:08 +03:00
Nick Williams
80f908353f RadzenDialog Improvements (#550)
* Change to DatePicker to optionally pad the time picker hour, minute or seconds components with leading zeros. Corresponding new boolean parameters are PadHours, PadMinutes and PadSeconds.

* Fixed issue with RadzenDialog where closing a nested dialog removed the 'no-scroll' class from the page body, allowing the background to scroll. The javascript 'closeDialog' function is now only invoked when the last dialog is closed.
Added a  potential impovement to RadzenDialog, whereby the dialog mask is only shown for the top most dialog, rather than the accumulative effect of multiple masks. This might be personal perference, but makes more sense to me.
2022-08-01 08:30:27 +03:00
Atanas Korchev
a3a8ad87d3 Trend lines do not render in some cultures. 2022-07-28 19:10:04 +03:00
Vladimir Enchev
ea52a7a9ec Version updated 2022-07-28 08:30:37 +03:00
Vladimir Enchev
972042645c PagedDataBoundComponent FirstPage() method logic with forceReload fixed 2022-07-28 08:29:37 +03:00
Nick Williams
e01c8d4e13 Change to DatePicker to optionally pad the time picker hour, minute or seconds components with leading zeros. Corresponding new boolean parameters are PadHours, PadMinutes and PadSeconds. (#544) 2022-07-27 08:37:11 +03:00
Vladimir Enchev
351373aea5 Fixed Mask component will not apply mask initially 2022-07-26 19:55:05 +03:00
Vladimir Enchev
287680df87 Fixed DataGrid virtualization not working properly in Firefox 2022-07-26 15:13:21 +03:00
Vladimir Enchev
aa96a98722 Fixed validators not working in DataGrid in-line edit with grouping 2022-07-26 09:00:46 +03:00
Vladimir Enchev
58aa231cd2 Version updated 2022-07-25 08:58:02 +03:00
Vladimir Enchev
d0a59e9d6f DataGrid LoadData called twice on FirstPage() with top and bottom pagers 2022-07-25 08:46:00 +03:00
Vladimir Enchev
972c278356 Fixed DataGrid enum filtering
Fix #542
2022-07-25 08:28:25 +03:00
Vladimir Enchev
d3b236107b Version updated 2022-07-23 09:21:20 +03:00
Vladimir Enchev
ddd359afe0 Fixed DropDown multiple selection
Fix #540
2022-07-23 09:20:59 +03:00
Vladimir Enchev
0278777ff4 Version updated 2022-07-21 18:21:07 +03:00
Vladimir Enchev
c8b703778b page restored 2022-07-21 18:19:45 +03:00
Vladimir Enchev
a0d49f8c29 Fixed DropDown does not throw errors within an async Task set to the Change event
Fix #537
2022-07-21 18:19:28 +03:00
Marco Papst
93f9a318b0 allow override of Template with ChildContent in BreadCrumbItem (#536)
Co-authored-by: Marco Papst <papst@sma.de>
2022-07-21 08:54:02 +03:00
pigwing
bc6679505d add ShowEmptyMessage attribute (#535)
* add DisableEmptyText attribute fix when AllowPaging = true && LoadData.HasDelegate && Count == 0 DataGrid InLine Editing not working

* adopt a suggestion
2022-07-21 08:53:15 +03:00
Vladimir Enchev
5698e1a4fb Fixed Accrodion exception when set Visible property of the item 2022-07-21 08:51:26 +03:00
Vladimir Enchev
61c39a8919 Fixed numeric input with zero min/max
Fix #533
2022-07-19 17:09:57 +03:00
Vladimir Enchev
ae2e8b6abd Version updated 2022-07-19 09:23:53 +03:00
Vladimir Enchev
e1bce30ee3 DataGrid simple mode filtering by date will not show value if filter is not applied 2022-07-19 09:23:33 +03:00
Vladimir Enchev
44da884057 Fixed Numeric input and paste logic when min/max is set
Fix #532
2022-07-19 08:58:14 +03:00
Vladimir Enchev
7f9f05ae0e Version updated 2022-07-18 15:40:49 +03:00
Vladimir Enchev
4638d173b6 Order of FileInput events during file remove fixed 2022-07-18 14:46:47 +03:00
Vladimir Enchev
43bc3cee06 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-07-18 09:00:05 +03:00
Vladimir Enchev
2db68559d5 FileInput FileName and FileSize parameters added 2022-07-18 08:59:46 +03:00
glutio
122b07b757 Do not show trend tooltip if the line is not visible and fix line names (#531)
* Do not show trend tooltip if the line is not visible and fix line names
Revert accidental removal of commit 6b9d2c19a7 (FilterCleared event)

* Fixed trend lines length and contains() method
2022-07-15 14:32:01 +03:00
Atanas Korchev
d6760ca4b9 Having async code in Expand handler sometimes prevents RadzenTreeItem from rendering. 2022-07-15 14:26:02 +03:00
Vladimir Enchev
fe036e75a3 Version updated 2022-07-14 09:51:03 +03:00
Vladimir Enchev
a574e77f0a Numeric oninput and onpaste attributes fixed
Fix #524
2022-07-14 09:50:08 +03:00
Vladimir Enchev
b4c885067d Fixed FileInput will not select the same file if already removed 2022-07-14 09:10:03 +03:00
glutio
200fb9d9ee Chart overlays - data labels, trends and annotations. 2022-07-13 17:31:48 +03:00
Vladimir Enchev
ec06fdcda6 DropDownBase clear selection using delete key will respect AllowClear property 2022-07-13 14:01:06 +03:00
Atanas Korchev
fb31cc7268 Add missing comma 2022-07-12 16:53:38 +03:00
Atanas Korchev
afdbf2ac0b Set example titles. 2022-07-12 16:43:21 +03:00
Vladimir Enchev
4197230ffd Version updated 2022-07-12 07:24:01 +03:00
Vladimir Enchev
952e22367e Fix DropDownDataGrid selected value not displayed properly in some cases 2022-07-12 07:21:18 +03:00
Atanas Korchev
a497660c64 Prevent exceptions if the value entered in the numeric filter is invalid. Closes #523 and #522. 2022-07-11 16:17:17 +03:00
Vladimir Enchev
bd3f4e08b2 DropDownBase SelectedItems reverted 2022-07-08 18:43:11 +03:00
Vladimir Enchev
c2e5aba0e4 SelectedItems/SelectedItemsChanged added to DropDownBase 2022-07-08 17:45:43 +03:00
Vladimir Enchev
729cf2c033 Fixed DataGrid filtering with virtualization enabled not refreshing UI 2022-07-08 16:17:46 +03:00
Vladimir Enchev
2633bd46c3 Improved Numeric min/max validation 2022-07-08 09:06:11 +03:00
Vladimir Enchev
f6430d421e Fixed DatePicker AM/PM should be clicked multiple times in some cases 2022-07-08 08:14:02 +03:00
Vladimir Enchev
1045290320 Fixed DataGrid group header cell colspan not correct in case of Template defined 2022-07-08 08:00:28 +03:00
Vladimir Enchev
0416bb20b3 DataGrid advanced filtering more fixed with IsEmpty/IsNotEmpty 2022-07-07 16:03:47 +03:00
130nk3r5
cb7223dee1 RadzenDataGrid: Added Is Empty and Is not empty Filter operators (#514)
* Updated the RadzenDataGrid's filter operators too have a 'Is Empty' and 'Is not empty' Options

* IsNull/IsNotNull should work with null while IsEmpty/IsNotEmpty with empty string

Co-authored-by: Hugo Human <hugo@tangentsolutions.co.za>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2022-07-07 15:14:30 +03:00
Vladimir Enchev
59b535b0d8 Version updated 2022-07-07 10:27:11 +03:00
glutio
6b9d2c19a7 Add FilterCleared event to DataGrid to fire when filter is clered to allow custom logic to tell the difference between operator/value change and filter clear event. In my case it allows me to keep the operator even though it's reset to default in ClearFilter(). (#506)
Co-authored-by: Eugene Pistrak <evpistra@microsoft.com>
2022-07-07 10:25:26 +03:00
Vladimir Enchev
3d7fbefa24 Fixed DatePicker months and years drop downs not update on Min/Max change 2022-07-07 09:46:28 +03:00
Vladimir Enchev
24311c2e71 Fixed FileInput not showing file name and size if not image 2022-07-07 08:32:21 +03:00
Vladimir Enchev
93db8cc163 Fixed DataGrid column Type property not initialized correctly in some cases 2022-07-06 14:09:26 +03:00
Vladimir Enchev
bdd833e05b DataGrid dynamic data demo simplified 2022-07-05 11:13:52 +03:00
Vladimir Enchev
64bcb9b4c3 DataGrid demo with dynamic data reworked 2022-07-05 11:01:54 +03:00
Vladimir Enchev
6f2cf36ba6 Fixed Numeric value change with percent format 2022-07-04 09:52:13 +03:00
Vladimir Enchev
4828af7130 DataGrid Reset() method should respect FilterOperator for string and IEnumerable columns 2022-07-01 16:39:44 +03:00
Vladimir Enchev
0d0aa7c9a0 Do not attempt to filter collections with non valid comparison 2022-06-30 19:27:02 +03:00
Atanas Korchev
f0c962fde0 Toggling the Visible property of a form component breaks validation. 2022-06-30 18:25:13 +03:00
yordanov
a04197f145 Fix grid cell border-bottom in nested grids 2022-06-30 10:41:10 +03:00
Vladimir Enchev
530e9b05ef ListBox/DropDown select all CheckBox checked logic improved 2022-06-30 09:53:34 +03:00
Vladimir Enchev
5276b5f9f7 Version updated 2022-06-30 09:36:18 +03:00
Vladimir Enchev
9a8f5f7186 DataGrid column methods for get/set filter values and operators made public 2022-06-30 08:56:29 +03:00
Vladimir Enchev
7de2b3567d DropDown ValueTemplate property added 2022-06-29 17:14:00 +03:00
Vladimir Enchev
2a53fd6f13 DataGrid Filter event will be raised on clear filter from column filter menu 2022-06-28 08:40:47 +03:00
Vladimir Enchev
1092fd4198 Version updated 2022-06-23 12:16:20 +03:00
Vladimir Enchev
dd5619c1f9 Fixed DropDownDataGrid delegate to an instance method cannot have null 'this' 2022-06-23 12:16:05 +03:00
Vladimir Enchev
06cffc101f Version updated 2022-06-23 10:18:29 +03:00
Vladimir Enchev
5f17dae777 Fixed DropDownBase selected item cannot be removed 2022-06-23 10:04:55 +03:00
Vladimir Enchev
001a8a276f ListBox multiple selection fixed with virtualization enabled 2022-06-22 15:44:16 +03:00
Vladimir Enchev
16986f0f56 DataGrid clear filter added to the filtering menu 2022-06-22 11:09:30 +03:00
Vladimir Enchev
36ff2808bd Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-06-22 10:36:08 +03:00
Vladimir Enchev
b566e10847 Should execute DataGrid Reload() on LogicalFilterOperator and FilterCaseSensitivity change 2022-06-22 10:36:01 +03:00
TheNoNinja
1b4fbf17a8 Get total item count after loading the data into the datagrid (#500)
Co-authored-by: ChristiaanBrant <Christiaan.Brant@Notilyze.com>
2022-06-22 10:30:38 +03:00
Vladimir Enchev
1475b1a299 Fixed DataGrid will not clear all filters on Reset() 2022-06-22 10:22:59 +03:00
Vladimir Enchev
147c5455ff Fixed DropDownDataGrid will not clear selection when set @bind-Value to null 2022-06-22 10:18:36 +03:00
Vladimir Enchev
73bfd9b66c Fixed collection was modified exception with async data binding 2022-06-22 09:15:40 +03:00
Atanas Korchev
f5fa061392 Improve Chart tooltip positioning. Reduce the number of roundrips required to display a tooltip. 2022-06-21 14:57:26 +03:00
Atanas Korchev
71b50171de Delete unnecesary Category() call. Allow toggling the visibility of series in LegendClick. 2022-06-21 11:54:18 +03:00
Paul Ruston
a172caba24 LegendClick after fork recreate 202206181900 2022-06-21 11:54:18 +03:00
Vladimir Enchev
ab39c3bbdb ContextMenu removed from tree demo 2022-06-20 11:36:27 +03:00
Vladimir Enchev
29733cc474 ContextMenu example added to Tree demo 2022-06-20 11:35:29 +03:00
Vladimir Enchev
00a358cfb6 Radzen.Blazor PackageReference Version set to * 2022-06-20 10:39:50 +03:00
Vladimir Enchev
000475884d DropDownDataGrid CellRender and RowRender events added
Fix #496
2022-06-20 10:10:05 +03:00
Vladimir Enchev
49b2cda0c2 Fixed Chromium browsers will crash on popup open from frozen cell 2022-06-20 09:57:44 +03:00
Domen
fdf229400a Removed duplicated code from SCSS, Changed positionCSS 2022-06-17 10:12:22 +03:00
Domen
c79d485d69 Added TopRight and BottomRight position to TabPositon 2022-06-17 10:12:22 +03:00
Vladimir Enchev
3f9aa621d1 Version updated 2022-06-16 10:06:17 +03:00
Atanas Korchev
c94c00d933 Expose the EditContext property of RadzenTemplateForm as a parameter. 2022-06-15 13:36:47 +03:00
Max Reble
e540855bf9 fixes #471
if endtime is > 24h appointments now will be shown
2022-06-15 13:32:11 +03:00
Johan
e3d55f4e3d Possible to set placeholder for HtmlEditorFormatBlock 2022-06-14 16:03:07 +03:00
Johan
988fc92456 Possible to set placeholder for HtmlEditorFontSize 2022-06-14 16:03:07 +03:00
Johan
c02b153ef1 Possible to set placeholder for HtmlEditorFontName 2022-06-14 16:03:07 +03:00
Atanas Korchev
70ca4893ba Make the title inline. 2022-06-14 15:58:34 +03:00
Carsten Heinrich
4e15d3779c Change span to div to enable a valid <h..> inside 2022-06-14 15:58:34 +03:00
Atanas Korchev
f924a18d07 Temporarily use strings for categories. 2022-06-14 08:27:07 +03:00
Vladimir Enchev
bce1ec1c66 Version updated 2022-06-13 15:28:28 +03:00
Vladimir Enchev
7c4347ad9b Fixed error when navigating to route
Fix #485
2022-06-13 15:27:35 +03:00
Vladimir Enchev
820c594c1e Fixed low level example categories not expanded on filter 2022-06-13 10:45:25 +03:00
thedomingo
5c2d319b3a Add ProgressBarStyle to RadzenProgressBar (#482)
* Added ProgressBarStyle to ProgressBar

* Added test and demo

* Improved css, updated test, updated demo page
2022-06-13 09:21:17 +03:00
Instant.SC
ff62cc55c2 Fix right edge cropping of the filter button (#484) 2022-06-13 09:19:33 +03:00
Atanas Korchev
dee872fec2 Expose TickDistance to allow developers to set it. 2022-06-09 10:17:11 +03:00
Vladimir Enchev
87b670ca4e version updated 2022-06-09 09:15:54 +03:00
Vladimir Enchev
60c4c2f526 Fixed DataGrid infinite loop with LoadData and virtualization 2022-06-03 15:41:29 +03:00
yordanov
6fd03f826c Fix links alignment in breadcrumb 2022-06-03 14:30:09 +03:00
Vladimir Enchev
365cdb9fef Version updated 2022-06-02 09:15:39 +03:00
Vladimir Enchev
4342602202 Changing Tabs item visibility will reset selected tab to first in TabRenderMode.Client 2022-06-02 09:14:49 +03:00
Atanas Korchev
a168c10938 RadzenHtmlEditor sometimes does not allow specifying the text when the insert link tool is used. 2022-05-31 10:22:33 +03:00
Vladimir Enchev
09da6f870a Fixed DropDownDataGrid selection when AllowRowSelectOnRowClick is set to false 2022-05-30 11:32:14 +03:00
Vladimir Enchev
8a4b334d20 ContextMenu should not be closed when expanding child items 2022-05-27 15:40:11 +03:00
Atanas Korchev
4f6916a2df RadzenUpload can have an Icon. 2022-05-27 13:19:24 +03:00
Vladimir Enchev
14a9c94944 Export demo and controller updated 2022-05-26 11:41:56 +03:00
Atanas Korchev
6ad0fda364 Update documentation about .NET 6 and use Blazor Server and Blazor WebAssembly. 2022-05-26 10:20:27 +03:00
Atanas Korchev
491c124ac1 The HeadOutlet was not rendered correctly. 2022-05-26 10:20:27 +03:00
Vladimir Enchev
81cb7b4f84 Radzen.Blazor version updated 2022-05-26 10:07:53 +03:00
Vladimir Enchev
90c91c2b16 DataGrid group cannot be expanded when collapsed on first render in GroupRowRender
Fix #472
2022-05-26 09:57:17 +03:00
Vladimir Enchev
161d2810a3 Fixed DropDownDataGrid @bind-Value will not select item when bound using LoadData 2022-05-26 09:46:33 +03:00
Vladimir Enchev
9c0dae8d9a DataGrid boolean column filtering toggle fixed 2022-05-25 11:57:14 +03:00
Vladimir Enchev
6375be4d2c Virtualize panel will need double refresh when using LoadData :( 2022-05-25 11:37:00 +03:00
Atanas Korchev
64234815cc Do not check parent checkbox if AllowCheckParents is false. 2022-05-25 11:17:33 +03:00
Vladimir Enchev
b56d4d1ca3 Fixed virtualized DropDownDataGrid not reloaded properly on clear filter when bound using LoadData 2022-05-23 16:02:50 +03:00
Vladimir Enchev
8d31b287f2 Version updated 2022-05-23 09:31:16 +03:00
Vladimir Enchev
8e59d905ba Demos filtering fixed
#470
2022-05-23 09:30:16 +03:00
Vladimir Enchev
028661f9f8 Fixed DataGrid sorting when grouped 2022-05-20 10:26:05 +03:00
Vladimir Enchev
f6189c6d8a Version updated 2022-05-19 09:31:03 +03:00
Vladimir Enchev
ee677ced24 Fixed DropDownDataGrid selected item lost on paging when using LoadData binding 2022-05-18 09:40:16 +03:00
Vladimir Enchev
5f5c142d03 Fixed DropDownDataGrid will not select item on initial value set using @bind-Value 2022-05-18 09:18:54 +03:00
Benjamin Vertonghen
2a7fe455ad FIX GetDescription instead of Description for localization Enum Filter (#463) 2022-05-17 08:59:46 +03:00
Vladimir Enchev
047469de5b Version updated 2022-05-16 09:48:55 +03:00
Benjamin Vertonghen
7a61a68f00 Add Display Attribute and localization for Enum Filter (#455)
* Add Display Attribute and localization

* Fix simple mode and use actual value not string.
2022-05-12 16:01:23 +03:00
SUBRAHMANYA ORUGANTI
50f71390f8 Made RadzenDataGridColumn.GetValue as virtual 2022-05-09 14:25:13 +03:00
Vladimir Enchev
fba7bb68fe Version updated 2022-05-09 09:49:59 +03:00
Vladimir Enchev
2f6749bf5e DatePicker TimeOnly parse fixed 2022-05-04 08:52:08 +03:00
Vladimir Enchev
9253c6dd7b DataGrid enum filter enabled for Simple and SimpleWithMenu filtering modes. EnumFilterSelectText property added. 2022-05-03 13:31:14 +03:00
Vladimir Enchev
e23ad8239b Version updated 2022-05-02 12:38:25 +03:00
Vladimir Enchev
2f9e624c31 Drag demo deleted 2022-04-29 16:01:11 +03:00
Vladimir Enchev
a336b50e0f Drag Documentation and Heading turned off 2022-04-29 15:23:27 +03:00
Vladimir Enchev
5bc4a96e77 empty comit 2022-04-29 15:17:06 +03:00
Vladimir Enchev
113ba8223c Drag example added 2022-04-29 15:00:57 +03:00
Vladimir Enchev
a760150d75 Null ref. exception fixed 2022-04-29 09:27:28 +03:00
Vladimir Enchev
42a52dc606 DataGrid group by column will use ascending sort order if column is not sorted 2022-04-28 15:02:30 +03:00
Vladimir Enchev
b0c45c115e Fixed AutoComplete e.target.closest is not a function error 2022-04-28 14:55:09 +03:00
Vladimir Enchev
6a427a04ff DataGrid Groups.Clear() will not restore column visibility if HideGroupedColumn=true 2022-04-28 10:48:55 +03:00
Vladimir Enchev
1959c009fd version updated 2022-04-28 07:13:51 +03:00
Vladimir Enchev
35f5bdd483 DataGrid UpdatePickableColumn() exception fixed 2022-04-28 07:13:43 +03:00
Vladimir Enchev
ff422bae19 Version updated 2022-04-27 11:46:53 +03:00
Vladimir Enchev
f2e4d5cc1b Tooltip arrow render lag fixed 2022-04-27 11:45:26 +03:00
Vladimir Enchev
5fba69cad3 Context menu closed on item click 2022-04-27 10:19:12 +03:00
Vladimir Enchev
a1385956aa Step item Template property added 2022-04-27 10:08:11 +03:00
Atanas Korchev
9493cbc6ff RadzenUpload cannot upload files larger than 2GB. Breaking change if using the UploadProgressArgs class 2022-04-27 08:59:15 +03:00
Vladimir Enchev
0762841ef0 DataGrid enum filtering example added 2022-04-26 10:43:48 +03:00
Vladimir Enchev
e94fb73fd2 Numeric Format not applied if value is deleted and changed to the same
Fix #437
2022-04-26 09:25:39 +03:00
Atanas Korchev
6cb5f738d4 Certain component styles (info) do not work in tr-TR culture. 2022-04-25 11:21:29 +03:00
Benjamin Vertonghen
1b66d6fe4d DataGrid Filtering on Enum and Nullable Enum (#435)
* Enum Filtering

* Typo
2022-04-25 07:58:29 +02:00
Vladimir Enchev
3a9511a6b2 Radzen.Blazor version updated 2022-04-21 09:30:46 +03:00
Vladimir Enchev
70cfcda727 Fieldset should not render legend if not needed 2022-04-21 08:46:44 +03:00
Vladimir Enchev
ef7ab11078 DataGrid column picker not update on column Visible change
Fix #432
2022-04-20 09:36:23 +03:00
Vladimir Enchev
14ad9618d3 Dashboard DataGrid user filtering improved 2022-04-20 09:09:54 +03:00
Andrew Buchanan
41ce3d862c Add Minimum Date, Maximum Date, Initial Month/Year, and SameStyleForA… (#409)
* Add Minimum Date, Maximum Date, Initial Month/Year, and SameStyleForAllDays

* Rename DatePicker MinimumDate/MaximumDate Parameters to Min/Max.  Rename InitialMonth to InitialViewDate. Remove new SameStyles Parameter and replace it with a new class rz-datepicker-other-month.

Co-authored-by: Andrew Buchanan <andrew@addos.ca>
2022-04-19 16:04:06 +03:00
Vladimir Enchev
2ae9e8bb6f DataGrid groups expand/collapse fixed when GroupFootersAlwaysVisible=true
Fixed #430
2022-04-19 13:41:26 +03:00
Vladimir Enchev
8ebdaee97f Version updated 2022-04-18 09:06:25 +03:00
Vladimir Enchev
9dab0f0c03 Fixed TabIndex not properly working for RadzenDropDownDataGrid
Fix #427
2022-04-15 10:33:47 +03:00
Vladimir Enchev
3144a6b5fd Various DataGrid examples title fixed 2022-04-15 09:53:23 +03:00
Vladimir Enchev
f6ed045b8f Fixed Numeric spinner icon hiding value partially 2022-04-15 09:49:21 +03:00
Atanas Korchev
b31c29b440 Allow the user to set the style of a splitter pane. 2022-04-14 16:04:33 +03:00
Atanas Korchev
0bf4181056 Use self-hosted analytics. 2022-04-14 09:01:54 +03:00
Vladimir Enchev
ff3fc84563 Version updated 2022-04-13 09:51:42 +03:00
Vladimir Enchev
644af53193 DataGrid group row expand state not persisted when set in GroupRowRender FirstRender
Fix #425
2022-04-13 09:48:52 +03:00
yordanov
b52eb24e85 Add banner 2022-04-12 13:04:21 +03:00
douglassimaodev
b0ee04fab2 Fixing error when YearRange is set but from calledar arrow <, > was allowing changing to a different year (#423)
Co-authored-by: douglas <douglas.simao@sgs.com>
2022-04-12 08:59:20 +03:00
yordanov
0b01f5ec1c Update readme content 2022-04-11 17:34:14 +03:00
Vladimir Enchev
310a2f5443 DropDown and ListBox items key set improved 2022-04-11 16:49:15 +03:00
Vladimir Enchev
9c7de1a8fe empty commit 2022-04-11 10:38:41 +03:00
Vladimir Enchev
2ff2d55f25 Version updated 2022-04-11 10:20:20 +03:00
Vladimir Enchev
3d5e7be6b6 DataGrid not updated after column OrderIndex change runtime 2022-04-11 10:16:01 +03:00
Vladimir Enchev
4bce655cb6 DataGrid string columns IsNull/IsNotNull filtering fixed 2022-04-11 09:40:14 +03:00
Peter Egunjobi
f2aa01d23c Dropdown reinitialization fix (Resolves #419) (#420)
* Update RadzenListBox.razor.cs

```item``` is a reference object, and this is not situable to be used as a key, because it is likely to change even though the properties of the object remain unchanged. Instead, we should use the ```ValueProperty``` as the key. This is most likely to be a primitive and also unique. If it isn't provided, the ```item``` is used (from what I understand about the ```PropertyAccess.GetItemOrValueFromProperty()``` implementation.

* Update RadzenDropDown.razor.cs

```item``` is a reference object, and this is not situable to be used as a key, because it is likely to change even though the properties of the object remain unchanged. Instead, we should use the ```ValueProperty``` as the key. This is most likely to be a primitive and also unique. If it isn't provided, the ```item``` is used (from what I understand about the ```PropertyAccess.GetItemOrValueFromProperty()``` implementation.
2022-04-11 09:16:44 +03:00
Atanas Korchev
37907ed7f6 Set bar and column series tooltip border to Fill or Fills if specified. 2022-04-08 10:51:20 +03:00
yordanov
17d34ae443 Add link to component's source code 2022-04-07 16:35:35 +03:00
Vladimir Enchev
5e442d43aa Version updated 2022-04-07 07:22:30 +03:00
Atanas Korchev
3594c81b17 Introduce a Hidden property for chart series which allows the developer to hide a series bit still make it show later by clicking the corresponding label in the legend. 2022-04-06 18:38:14 +03:00
Atanas Korchev
221c830d60 Set line and area series border to stroke or fill if specified. 2022-04-06 18:27:13 +03:00
Atanas Korchev
962c2db587 RadzenChart sometimes displays a tooltip for the wrong series. 2022-04-06 18:19:31 +03:00
yordanov
e22d3367ba Update BreadCrumb styling and demo 2022-04-06 13:09:38 +03:00
Marco Papst
27df815529 fix parameter name in breadcrumb page demo 2022-04-06 11:33:02 +03:00
Marco Papst
64ad14ae80 revert files 2022-04-06 11:33:02 +03:00
Marco Papst
3de09dc8db fix code style 2022-04-06 11:33:02 +03:00
Marco Papst
170aede49f revert files 2022-04-06 11:33:02 +03:00
Marco Papst
9ab740e53b add Id to RadzenBreadcrumb 2022-04-06 11:33:02 +03:00
Marco Papst
ddd4a806e1 replace items with child content 2022-04-06 11:33:02 +03:00
Marco Papst
5b4b427589 add docs page 2022-04-06 11:33:02 +03:00
Marco Papst
67900764f0 format tests 2022-04-06 11:33:02 +03:00
Marco Papst
df3995f0bb rework RadzenBreadCrumb to allow Child Items 2022-04-06 11:33:02 +03:00
Marco Papst
96278eb6d4 rework RadzenBreadCrumb to allow child items 2022-04-06 11:33:02 +03:00
Marco Papst
b012abbffb add Bread Crum Examples 2022-04-06 11:33:02 +03:00
Marco Papst
cd52110e95 add BreadCrumb Tests 2022-04-06 11:33:02 +03:00
Marco Papst
eba00e0e26 add BreadCrumb Component 2022-04-06 11:33:02 +03:00
Atanas Korchev
baab38c7f6 Prevent out of range exceptions in pie and donut tooltips. 2022-04-05 10:09:13 +03:00
Vladimir Enchev
539530bcb9 DropDown cannot select item when OpenOnFocus is set to true and already focused 2022-04-04 08:03:00 +03:00
Vladimir Enchev
829cdec53c Version updated 2022-03-31 08:59:54 +03:00
Vladimir Enchev
1bbe89f962 DatePicker rz-datepicker-title inline style height removed 2022-03-31 08:50:58 +03:00
Vladimir Enchev
1ae9724d34 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-03-30 11:52:50 +03:00
Vladimir Enchev
d71142a253 OpenOnFocus checked when opening from click 2022-03-30 11:52:48 +03:00
Atanas Korchev
ca0437d765 RadzenScheduler events do not take MinutesPerSlot into account. 2022-03-30 10:30:17 +03:00
Vladimir Enchev
7e4619c2ae DropDown and DropDownDataGrid OpenOnFocus property added 2022-03-30 09:49:41 +03:00
Vladimir Enchev
65dd9e26e9 DropDownDataGrid open on ENTER key added 2022-03-30 09:40:37 +03:00
Vladimir Enchev
fe788ca5dc code fixed 2022-03-30 09:25:48 +03:00
Vladimir Enchev
4e3fd87481 Fixed SelectBar will not select item with null value 2022-03-30 09:21:18 +03:00
Trent Adams
6244663e80 Updated Index.md (#407)
Spelling issue in regards to support. Fixed "of you require" to "if you require..."
2022-03-30 09:00:50 +03:00
Vladimir Enchev
3bce988e12 DataGrid column GetVisible() made public 2022-03-29 16:55:07 +03:00
Vladimir Enchev
0fcc9e112a Version updated 2022-03-28 10:22:14 +03:00
Vladimir Enchev
d083ae6d0e Fixed DatePicker changing AM/PM not working in some cases 2022-03-28 09:44:57 +03:00
Vladimir Enchev
ddffc72e76 Fixed ContextMenu opens only once in WASM 2022-03-28 09:28:42 +03:00
Atanas Korchev
20d22fa036 CheckBox does not work inside <label> 2022-03-27 21:08:29 +03:00
Vladimir Enchev
ccb923ecc4 project updated 2022-03-25 15:31:09 +02:00
Vladimir Enchev
90f98c69c5 Version updated 2022-03-25 15:14:06 +02:00
acordts
2f273777b2 remove label attribute from span tag (fix #403) (#404)
Co-authored-by: Albrecht Ziegler-Cordts <albrecht.ziegler-cordts@t-systems.com>
2022-03-25 10:56:01 +02:00
Vladimir Enchev
3936960caf DataGrid OrderByDescending() method fixed
Fix #402
2022-03-25 10:08:52 +02:00
Vladimir Enchev
e32262a3b3 DataGrid HideGroupedColumn fixed to work with runtime add of GroupDescriptor 2022-03-25 10:00:31 +02:00
Vladimir Enchev
bc9d7f7c2a DatePicker exception with DateTime.MinValue fixed 2022-03-25 09:38:04 +02:00
mrossberg
71fe870b1d On Disposal of RadzenSplitButton: Close popup (#401) 2022-03-24 16:07:54 +02:00
Vladimir Enchev
28a0456fa7 Version updated 2022-03-24 09:42:11 +02:00
Vladimir Enchev
ad7e00add5 DataGrid ShowMultiColumnSortingIndex property added 2022-03-22 11:46:41 +02:00
Vladimir Enchev
6e5749063c DataGrid Group event and HideGroupedColumn property added 2022-03-22 10:27:09 +02:00
Vladimir Enchev
048de253a9 DataGrid Sort, Filter and Page events added 2022-03-22 10:05:11 +02:00
Vladimir Enchev
c6c9578691 version updated 2022-03-21 11:23:33 +02:00
Vladimir Enchev
b052c04749 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-03-21 09:35:22 +02:00
Vladimir Enchev
5085255f61 DataGrid column CloseFilter() method added 2022-03-21 09:35:14 +02:00
Atanas Korchev
cd306135ad Remove setTitle invocation. 2022-03-21 09:22:27 +02:00
Vladimir Enchev
fbb9cac178 Fixed DropDown item requires two clicks to select 2022-03-18 10:22:04 +02:00
Vladimir Enchev
291210aadf DataGrid columns picker text properties added 2022-03-18 09:30:38 +02:00
Vladimir Enchev
458a9b9907 DropDownDataGrid click to open popup area fixed 2022-03-17 17:51:24 +02:00
mmmmmarco
d210feab0d Datepicker footer placeholder (#400)
* Toevoegen footer template

* Add unit test

* Add demo

* Don't render footer if no footerTemplate is set
2022-03-17 14:45:45 +02:00
Vladimir Enchev
c3aaf78161 Version updated 2022-03-17 10:31:32 +02:00
Vladimir Enchev
a86c7c6c1e Reverted switch to default preprocessor constants 2022-03-17 10:31:07 +02:00
Vladimir Enchev
8f79204fbc Version updated 2022-03-17 10:05:46 +02:00
Vladimir Enchev
c21823c84e code fixed 2022-03-17 10:04:04 +02:00
Vladimir Enchev
c40f64a193 code fixed 2022-03-17 09:54:39 +02:00
Vladimir Enchev
f42cd221cc Version updated 2022-03-17 09:10:25 +02:00
Vladimir Enchev
a8dc2a07db Added MarkupString support for Notification message 2022-03-16 11:16:53 +02:00
Vladimir Enchev
93e27f318d Tree CheckedValues exception fixed 2022-03-14 17:04:38 +02:00
Vladimir Enchev
7ecb3ccf46 DatePicker StartDate handles DateTime.MinValue 2022-03-14 10:54:10 +02:00
Marcel Roozekrans
1dd48aa3f1 DatePicker: Added support for DateTime Min and Max. (#394) 2022-03-14 10:48:18 +02:00
Vladimir Enchev
9ee7c6809a various tests fixed
#396
2022-03-14 09:36:26 +02:00
Vladimir Enchev
4eec46012a Switched to default preprocessor constants 2022-03-08 15:34:10 +02:00
Vladimir Enchev
455edff025 version updated 2022-03-07 10:30:41 +02:00
Vladimir Enchev
79a43fe897 Fixed DataGrid with virtualization calls LoadData 5 times on initial creation
Fix #392
2022-03-04 10:13:26 +02:00
Vladimir Enchev
34306f023c Numeric paste improved to accept numbers from string 2022-03-03 14:06:05 +02:00
Vladimir Enchev
e42baf816c Version updated 2022-03-03 09:27:15 +02:00
Atanas Korchev
f4cf76bc8f The id attribute of RadzenDropDown is used when generating the id of its popup. Allows styling specific popups. 2022-03-01 14:46:21 +02:00
Vladimir Enchev
d7ef57a24e DataGrid numeric columns LoadData Filter expression fixed for IsNull/IsNotNull 2022-02-28 17:14:56 +02:00
Vladimir Enchev
a349a3390c page updated 2022-02-28 16:27:12 +02:00
Vladimir Enchev
eae6e6ed8d Version updated 2022-02-28 10:44:32 +02:00
david-alonso-su
14d87875ae readFileAsBase64: set canvas size same as new image size. (#388)
Remove unnecesary parameters.
2022-02-25 10:40:01 +02:00
Vladimir Enchev
62d997c85a demo fixed 2022-02-25 10:28:21 +02:00
Vladimir Enchev
02f37b2eeb Tree will not dispose children on collapse (#387)
* Tree AllowToggleChildrenOnClient added

* Tree expand reworked
2022-02-25 10:27:13 +02:00
Vladimir Enchev
636e6b82be demo improved 2022-02-25 09:24:12 +02:00
Vladimir Enchev
72c544a512 DataGrid FilterMode=SimpleWithMenu will apply style to filter icon in case of active filter 2022-02-25 09:05:04 +02:00
Vladimir Enchev
97c7a4db17 DataGrid FilterMode=SimpleWithMenu will disable inputs in case of IsNull/IsNotNull filters 2022-02-25 08:59:30 +02:00
Atanas Korchev
aa8b4881ce Update CONTRIBUTING.md 2022-02-25 08:41:24 +02:00
Vladimir Enchev
c6d37a4281 demo marked as updated 2022-02-24 10:16:22 +02:00
Vladimir Enchev
05b269c0cf Version updated 2022-02-24 10:05:24 +02:00
Vladimir Enchev
07d14cee67 DataGrid simple filter with menu added (#384)
* DataGrid FilterMode SimpleWithMenu added

* filter menu improved

* DoesNotContain fixed

* DatePicker will open popup on input click if AllowInput=false

* rz-readonly to DatePicker input

* rz-readonly to datepicker theme
2022-02-23 08:54:51 +02:00
yordanov
70fb35bd25 Update Material icons font 2022-02-22 11:18:12 +02:00
Atanas Korchev
574f4f90da DonutChart glitches in cultures that use comma as decimal separator. 2022-02-21 17:45:14 +02:00
Vladimir Enchev
6a951e1325 demo fixed 2022-02-21 14:52:42 +02:00
Vladimir Enchev
4a1abadd09 Version updated 2022-02-21 13:04:53 +02:00
Vladimir Enchev
84bd0af02e DataGrid column Visible fixed when AllowColumnPicking is true
Fix #382 #381
2022-02-21 13:01:56 +02:00
david-alonso-su
115b838d3c RadzenFileInput: Add MaxWith And MaxHeight to resize FileInput Image. (#379) 2022-02-21 09:43:21 +02:00
Ben Gavin
13032e726b Support for Remove/Clear to the RadzenUpload control #376 (#377)
* ADD:  Support for Remove/Clear to the RadzenUpload control #376
FIX:  Preview URLs generated during file selection are not freed on removal

* FIX:  Clear local preview files on file re-selection

Co-authored-by: Ben Gavin <ben.gavin@corebts.com>
2022-02-21 09:37:14 +02:00
Vladimir Enchev
cf6efbaa2d DropDownDataGrid demo improved 2022-02-21 09:37:02 +02:00
pigwing
580db415d6 add AllowRowSelectOnRowClick property at RadzenDropDownDataGrid (#383)
* added missing PageSizeText parameter

* add AllowRowSelectOnRowClick property at RadzenDropDownDataGrid,when use DropDown component in RadzenDropDownDataGridColumn template,change the DropDown value will trigger RadzenDataGrid.OnRowSelect
2022-02-21 09:24:33 +02:00
Vladimir Enchev
30b2d1d913 DropDownDataGrid ValueTemplate property added 2022-02-18 16:47:25 +02:00
Vladimir Enchev
510b2bcdd5 Handle defined in razor DataGrid column OrderIndex 2022-02-18 14:51:15 +02:00
Vladimir Enchev
30856325be DataGridColumnReoderPage updated 2022-02-18 14:27:04 +02:00
Vladimir Enchev
a5ab34b707 DropDown, DropDownDataGrid and ListBox AllowClear when Value is not bound fixed 2022-02-18 13:29:29 +02:00
Vladimir Enchev
90ee139265 DataGrid column OrderIndex property added 2022-02-18 11:58:30 +02:00
Vladimir Enchev
1e298edbdd DataGrid state not updated properly after column reorder in .NET 3.1 2022-02-18 10:07:52 +02:00
Vladimir Enchev
925afb70c3 version updated 2022-02-18 08:51:07 +02:00
Vladimir Enchev
c399b850c5 DropDownDataGrid not updated properly on Data change 2022-02-18 08:50:45 +02:00
Vladimir Enchev
8cf03e3ee3 Version updated 2022-02-17 09:21:51 +02:00
Atanas Korchev
e6ba1fc61b Disable the responsive mode of RadzenSidebar if it is not nested inside RadzenLayout. 2022-02-16 15:37:43 +02:00
Vladimir Enchev
a2a434d6fd comment removed 2022-02-16 10:09:35 +02:00
Vladimir Enchev
fe00182efd various warnings fixed 2022-02-16 09:40:33 +02:00
Vladimir Enchev
b00fcc25ea DialogOptions CloseDialogOnEsc property added 2022-02-15 17:28:32 +02:00
Vladimir Enchev
e9624ab6d6 Close dialog on ESC added 2022-02-15 17:03:03 +02:00
Vladimir Enchev
c2d129aaa6 DropDown, ListBox and DropDownDataGrid wrong selection on Data change fixed 2022-02-15 09:24:08 +02:00
Vladimir Enchev
6b3b7d6945 version updated 2022-02-14 15:22:08 +02:00
Vladimir Enchev
1889b840b1 Menu and ProfileMenu z-index raised
Related to f5057c2ac7
2022-02-14 13:32:52 +02:00
Atanas Korchev
bfb1a4ef23 Unsubscribe from event before subscribing to avoid memory leaks. 2022-02-14 12:34:10 +02:00
Atanas Korchev
f178f31248 Icons are missing if the Text property of a scheduler view is set. 2022-02-14 11:43:31 +02:00
Vladimir Enchev
9c13832307 DataGrid frozen column styles not regenerated when column Visible changed runtime
Fix #371
2022-02-14 10:57:19 +02:00
Vladimir Enchev
1c3f87165e DataGrid column Pickable property added 2022-02-14 10:36:02 +02:00
Vladimir Enchev
c6ce339d40 DataGrid column MinWidth property added 2022-02-11 08:37:36 +02:00
Vladimir Enchev
5a90b00e19 Version updated 2022-02-11 08:27:34 +02:00
Atanas Korchev
e6bf8b5321 Add Responsive property to RadzenSidebar. 2022-02-10 16:35:20 +02:00
Atanas Korchev
156e493a90 Invoke own StateHasChanged when the Refresh method of DialogService is called. Fixes #363. 2022-02-10 15:43:35 +02:00
Vladimir Enchev
2cf073495c version updated 2022-02-10 14:33:11 +02:00
Vladimir Enchev
43b193e965 DropDown and DropDownDataGrid multiple selected items label fixed 2022-02-10 14:32:51 +02:00
yordanov
b4b8dfb217 Fix light button colors 2022-02-10 12:12:57 +02:00
Vladimir Enchev
99051af886 DataGrid Column Picker added
Based on https://github.com/radzenhq/radzen-blazor/pull/344
2022-02-10 10:58:09 +02:00
Vladimir Enchev
768926fec3 code fixed 2022-02-10 10:48:37 +02:00
yordanov
a73042abc1 Update RadzenGrid simple filtering UI 2022-02-09 18:29:48 +02:00
Vladimir Enchev
da36e3c1fa IJSRuntime param added 2022-02-09 13:59:17 +02:00
Vladimir Enchev
0024e3e74d Version updated 2022-02-09 10:58:30 +02:00
yordanov
9b14caf300 Delete commented styles 2022-02-09 10:55:16 +02:00
yordanov
adee153190 Update UI for simple mode filtering 2022-02-09 10:55:16 +02:00
Vladimir Enchev
c476cd7f25 Fixed #366 2022-02-09 10:30:00 +02:00
Vladimir Enchev
d4da6b02a8 LengthValidator not not notified when DropDownDataGrid value is selected 2022-02-08 11:10:41 +02:00
yordanov
1d3f651846 Add rz-body css class 2022-02-07 14:51:45 +02:00
yordanov
d6af0ffc95 Set translateZ to rz-body 2022-02-07 14:50:05 +02:00
yordanov
c1ba96d395 Add min-width to Pager's page buttons 2022-02-07 14:18:19 +02:00
Vladimir Enchev
52f53e3410 DropDownDataGrid EmptyTemplate added
Fix #359
2022-02-07 10:51:41 +02:00
Vladimir Enchev
aba4875cf3 version updated 2022-02-04 15:00:10 +02:00
Vladimir Enchev
f5057c2ac7 Revert fix for #339 2022-02-04 14:59:58 +02:00
Marc Mauri
cfd5558765 Reset Password shall throw event with an empty username (#360)
Co-authored-by: Marc Mauri <marc@kaizenforpharma.com>
2022-02-04 09:37:59 +02:00
Vladimir Enchev
77bbeb6de0 version updated 2022-02-03 13:32:25 +02:00
Vladimir Enchev
bf3e22bf4c DropDown, DropDownDataGrid and ListBox Value binding improved 2022-02-03 13:29:23 +02:00
Vladimir Enchev
a5596ac8f6 CheckBox typo fixed 2022-02-03 11:23:14 +02:00
Vladimir Enchev
a3dddfa7f8 DataGrid GroupRowExpand/GroupRowCollapse events added 2022-02-01 22:09:14 +02:00
Vladimir Enchev
922abe8ba3 DataGrid IsNull/IsNotNull filtering not working properly on columns bound to string property 2022-02-01 21:58:09 +02:00
Vladimir Enchev
9b85f8673c DialogService Confirm AutoFocusFirstElement support added 2022-02-01 21:46:01 +02:00
Vladimir Enchev
b8e0bf92c2 DataGrid simple filtering should respect column FormatString or DataGrid FilterDateFormat
Close #279
2022-02-01 09:59:07 +02:00
Vladimir Enchev
05c7adbfee Version updated 2022-01-31 14:51:36 +02:00
Benjamin Vertonghen
4081802dc8 FIX: Menu in DataGrid shows incorrectly due to z-index (#356)
* FIX: Menu in DataGrid

* rz-navigation-menu z-index lowered from 20 to 2

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2022-01-31 14:50:54 +02:00
Benjamin Vertonghen
45fb1cd801 Click on MenuItem (#354) 2022-01-31 12:21:10 +02:00
Vladimir Enchev
50ed4a6988 DataGrid header cell sorting outline border removed
We will try to provide better focus styles in our themes
2022-01-31 09:46:37 +02:00
Carsten Heinrich
96997e95a0 Enable sorting on RadzenDataGrid by keyboard (#351)
to increase the accessibility it is necassary to sort the RadzenDataGrid by keyboard

Co-authored-by: Carsten Heinrich <carsten.heinrich@t-systems.com>
2022-01-31 09:45:06 +02:00
Carsten Heinrich
9029a64a19 Insert additional header-attribute "aria-sort" so that the screen reader recognizes the sorting. (#358)
Co-authored-by: Carsten Heinrich <carsten.heinrich@t-systems.com>
2022-01-31 09:28:28 +02:00
Vladimir Enchev
cb6c9dd374 DataGrid cells colspan made recursive 2022-01-30 12:44:40 +02:00
Vladimir Enchev
5b1e9d3f16 DataGrid colspan fixed with multiple composite columns 2022-01-29 09:18:06 +02:00
Vladimir Enchev
ceb1f954ff DataGrid SecondFIlterValue not set to null on Reset() 2022-01-28 19:18:30 +02:00
Atanas Korchev
f67e4f953f DataGrid has gaps on desktop browsers in responsive mode. 2022-01-28 12:49:35 +02:00
Vladimir Enchev
76c071da14 FileInput ImageClick event added 2022-01-28 10:00:53 +02:00
Vladimir Enchev
c8dafae31d Version updated 2022-01-27 09:28:17 +02:00
Vladimir Enchev
1924056c02 Sidebar expand logic improved (#352)
* Add Sidebar expand and collapse CSS classes

* Initialize Expanded on load.

* Introduce RadzenMediaQuery.

* Use addListener instead of addEventListener to support older browsers.

* Fix redraw under WebKit

Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-01-27 09:26:25 +02:00
Vladimir Enchev
257dd22345 DataGrid grouping will not apply sorting if GroupDescriptor SortOrder is null 2022-01-27 09:22:24 +02:00
Vladimir Enchev
4211259874 Dialog bottom option setting fixed 2022-01-26 19:59:44 +02:00
Vladimir Enchev
9fa7d0182d Menu and ProfileMenu items should be over DataGrid header 2022-01-26 15:00:45 +02:00
Vladimir Enchev
8a00736c8f Frozen composite columns disabled
until we find a way to calculate properly left for frozen cells in composite columns
2022-01-26 13:47:36 +02:00
Vladimir Enchev
f1fd6b6d8b DataGrid composite columns colspan logic fixed 2022-01-25 20:03:07 +02:00
Ben Gavin
b1adad5866 FIX: Close popup when 'Tab'ing from control (#349)
FIX: Styling/layout fixes for validated control

Co-authored-by: Ben Gavin <ben.gavin@corebts.com>
2022-01-25 09:37:27 +02:00
Vladimir Enchev
f8aaa21b39 categories marked as updated 2022-01-24 14:35:53 +02:00
Vladimir Enchev
6b207e29fc Various demos marked as updated 2022-01-24 14:27:39 +02:00
Vladimir Enchev
4effb7cfdd Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-01-24 13:53:33 +02:00
Vladimir Enchev
83f48ac009 version updated 2022-01-24 13:53:24 +02:00
acordts
6788612ab5 add tabnavigation tabindex depending on disabled flag (#347)
Co-authored-by: Albrecht Ziegler-Cordts <albrecht.ziegler-cordts@t-systems.com>
2022-01-24 13:52:12 +02:00
Vladimir Enchev
8329c38894 DataGrid GroupRowRender event added 2022-01-24 11:26:11 +02:00
Vladimir Enchev
5e96f69c52 FileInput keyboard navigation improved 2022-01-24 09:30:18 +02:00
Atanas Korchev
f4c6b4f08d Always build SASS. 2022-01-21 11:47:36 +02:00
Vladimir Enchev
95fef77042 DataGrid AllowRowSelectOnRowClick property added (#341)
* DataGrid AllowRowSelectOnRowClick property added

* AllowRowSelectOnRowClick comment fixed

* DataGridMultipleSelection demo improved
2022-01-21 09:41:08 +02:00
pigwing
9814f44ead added missing PageSizeText parameter (#340) 2022-01-21 09:34:48 +02:00
Vladimir Enchev
13189c6c6c DataGrid header not working properly with bootstrap modal
Fix #339
2022-01-21 09:33:17 +02:00
Vladimir Enchev
aed16dfec6 version and demo updated 2022-01-20 16:17:45 +02:00
Vladimir Enchev
3167399da9 DataGridPagerHorizontalAlign fixed 2022-01-20 15:59:12 +02:00
Vladimir Enchev
c6b77fe861 version updated 2022-01-20 15:38:36 +02:00
yordanov
aa1e4ecb7d Update pager horizontal align in demos 2022-01-20 15:35:17 +02:00
yordanov
1b677770b6 Add Datagrid pager horizontal align demo page 2022-01-20 15:35:17 +02:00
Vladimir Enchev
c707f20b3f DataGrid, DataList and DropDownDataGrid PagerHorizontalAlign and PagerAlwaysVisible properties added 2022-01-20 15:35:17 +02:00
Vladimir Enchev
c368e065b6 Pager HorizontalAlign property added 2022-01-20 15:35:17 +02:00
yordanov
90eab0573f Add page size description text to Pager 2022-01-20 15:35:17 +02:00
yordanov
35d7286eec Add styles for Pager horizontal alignment modes 2022-01-20 15:35:17 +02:00
Vladimir Enchev
b68fe58a23 Revert: Fixed DataGrid template row cell not spanned on all columns 2022-01-20 15:07:59 +02:00
Vladimir Enchev
ea133a96cd Fixed DataGrid template row cell not spanned on all columns 2022-01-20 15:02:24 +02:00
Vladimir Enchev
69e48c77a9 Composite Columns marked as new, Columns as updated 2022-01-20 14:46:21 +02:00
Vladimir Enchev
606fb38ae6 Version updated 2022-01-20 13:27:45 +02:00
Vladimir Enchev
b29955d191 DataGrid AllowCompositeDataCells property added 2022-01-20 13:27:10 +02:00
Vladimir Enchev
7539fb3699 DataGrid thead fixed to not scroll vertically 2022-01-20 12:48:05 +02:00
Vladimir Enchev
2d8911947a DataGrid composite column cells right border fixed 2022-01-20 12:05:41 +02:00
Vladimir Enchev
2044042973 DataGridCompositeColumns source fixed 2022-01-20 10:11:15 +02:00
Vladimir Enchev
dd02f890c2 Sorting and filtering disabled for DataGridConditionalTemplate 2022-01-20 09:23:55 +02:00
Vladimir Enchev
45ca2eaaca Version updated 2022-01-20 09:18:47 +02:00
Atanas Korchev
aaf535c33f RadzenPanelMenu always highlights an item with Path set to "/". 2022-01-20 08:57:35 +02:00
Vladimir Enchev
e9c6da2c11 DataGrid simple filter header cell tabindex="1" removed 2022-01-19 14:41:51 +02:00
Atanas Korchev
e2c8efe29f Do not dispose if the timer is null. 2022-01-19 14:28:35 +02:00
Vladimir Enchev
e76b789eb7 DataGrid composite columns support added (#334)
* composite columns

* headers cells render reworked

* composite columns render reworked again

* footer cells support added for composite columns

* code improved

* Row details template expand fixed

* Group, resize and reorder disabled for composite columns

* composite columns demo improved
2022-01-19 13:31:17 +02:00
Vladimir Enchev
75d1431e50 DataGrid GroupDescriptor SortOrder property added. Column SortOrder will be used when grouping. 2022-01-18 21:05:26 +02:00
yordanov
8a9da8a3ae Style badge for new and updated demos 2022-01-18 11:13:01 +02:00
Atanas Korchev
3b718b0461 Top level navigation items can have a badge too. 2022-01-18 10:24:16 +02:00
Atanas Korchev
65b0d1fc23 Navigation items support badges. 2022-01-18 10:13:13 +02:00
Atanas Korchev
c56ed37f7a Remove scrollToBottom. 2022-01-18 09:54:43 +02:00
Vladimir Enchev
340754d062 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2022-01-18 09:50:21 +02:00
Vladimir Enchev
db85c34e61 DataGrid will render rows when binding using LoadData if paging is disabled and no Count set 2022-01-18 09:49:35 +02:00
Atanas Korchev
807995fe8b Use PageTitle and HeadContent. Find nested examples. 2022-01-18 09:41:22 +02:00
Atanas Korchev
111120edaa Allow the developer to set the slot size in day and week view of RadzenScheduler. 2022-01-17 09:11:07 +02:00
Vladimir Enchev
0bac8d6ae3 Pager AlwaysVisible and DataGrid PagerAlwaysVisible properties added
Close #319
2022-01-17 09:05:49 +02:00
yordanov
2ba17d8d5b Update copyright year 2022-01-14 11:38:44 +02:00
yordanov
a61633194d Update copyright year 2022-01-14 11:31:26 +02:00
yordanov
caa86bb931 Update copyright year 2022-01-14 11:27:52 +02:00
Vladimir Enchev
cfe08bc542 Version updated 2022-01-13 09:07:11 +02:00
yordanov
4e55742219 Separate Upload Choose button styles from btn-secondary styles 2022-01-12 17:23:41 +02:00
Vladimir Enchev
f98ed62045 Fix #330 2022-01-12 13:23:11 +02:00
Vladimir Enchev
03653fb653 Various components item remove improved to check if component is disposed 2022-01-12 11:11:10 +02:00
Vladimir Enchev
240a89da2c DatePicker input name attribute missing 2022-01-12 10:40:34 +02:00
Vladimir Enchev
cfacd05578 Themes SASS with LibSassBuilder instead WebCompiler (#332)
* Use LibSassBuilder instead of WebCompiler.

* Remove dotnet-tools.json.

* Remove logging.

* Build SASS only once.

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2022-01-12 10:23:32 +02:00
Vladimir Enchev
c0ab5f955d Fixed #322 2022-01-11 11:54:52 +02:00
Atanas Korchev
f2346c5709 HtmlEditor does not allow pasting of plain text. 2022-01-11 09:20:32 +02:00
Vladimir Enchev
798bfc964c Version updated 2022-01-10 10:32:46 +02:00
Marco Papst
2af9014962 Add IconStyle Property to RadzenIcon (#324) 2022-01-10 10:11:14 +02:00
GioeEng
f8759278bc Fixes (#315)
* New splitter component

* New Splitter component

* Fixed code style and naming conventions

* themes implemented

* Splitter: Error in icon representation. Incorrect design compromised panel behavior

* 0

* Rename variables

Co-authored-by: lorenzo <lorenzo.muccioli@car-tech.com>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
Co-authored-by: Vasil Yordanov <vasil@yordanov.info>
2022-01-07 12:22:37 +02:00
Lukas Grützmacher
abed1b0645 Wrap EmptyText in DataGrid (#323) 2022-01-07 09:27:14 +02:00
Vladimir Enchev
8999fc8fd6 Fixed RadzenNumeric error with unsigned integer types 2022-01-07 09:26:15 +02:00
Vladimir Enchev
a1f9db4114 Allow MarkupString to be used in Dialog Title 2022-01-07 09:20:53 +02:00
Vladimir Enchev
2336f1dc79 version updated 2022-01-06 09:32:54 +02:00
Atanas Korchev
335e177578 CheckBox uses click instead of mouseup. 2022-01-05 19:27:44 +02:00
Vladimir Enchev
a4434b16de DataGrid grouping support when virtualizing IQueryable 2022-01-05 10:46:48 +02:00
Vladimir Enchev
9b3624e818 Click on disabled date should not close the DatePicker
Fix #320
2022-01-04 09:53:35 +02:00
Vladimir Enchev
120a95f94d DataGrid will sort by grouped column 2022-01-04 08:57:40 +02:00
Atanas Korchev
db0a658be2 Cannot set the width of RadzenSplitButton. 2022-01-04 08:43:56 +02:00
yordanov
822a8afcb1 Add responsive styles to documentation-link 2021-12-30 16:11:18 +02:00
yordanov
eed371130f Rename link to component's docs 2021-12-30 16:11:18 +02:00
Vladimir Enchev
dd19c1040c Version updated 2021-12-30 09:25:10 +02:00
yordanov
54130e5ee7 Add responsive styles and icons to Scheduler nav views 2021-12-29 12:34:11 +02:00
Vladimir Enchev
827128d048 Slider will not calculate step properly when Min is set 2021-12-28 13:11:21 +02:00
Atanas Korchev
26c18562c4 PanelMenu matches URL which contain "-". Fixes #317. 2021-12-28 12:21:38 +02:00
Vladimir Enchev
0a847c8427 Version updated 2021-12-27 09:51:00 +02:00
yordanov
27a976fc53 DatePicker add cursor pointer to choosable dates - resolves #253 2021-12-24 15:59:21 +02:00
Atanas Korchev
73a3a881ca RadzenPanelMenu supports prefix matching. 2021-12-24 15:17:44 +02:00
Atanas Korchev
f07545285b Render theme stylesheet only once. 2021-12-24 15:05:57 +02:00
Vladimir Enchev
4d02883a48 ContextMenu should not show toggle button 2021-12-24 11:34:54 +02:00
yordanov
4eb9f0a0a4 Fix validator top padding in standard theme 2021-12-24 10:40:15 +02:00
Vladimir Enchev
1f630181d7 DataGrid filtering API demo updated 2021-12-23 19:55:11 +02:00
Vladimir Enchev
71a9b79527 version updated 2021-12-23 19:47:14 +02:00
Vladimir Enchev
b32d098d3b DataGrid column filter cannot be cleared even if specified in code 2021-12-23 19:47:06 +02:00
Vladimir Enchev
9118c1d64f version updated 2021-12-23 09:24:57 +02:00
Vladimir Enchev
8e4f7b0f08 DataGrid PageSize is wrong when using PageSizeOptions and LoadData
Fix #316
2021-12-23 09:24:46 +02:00
Vladimir Enchev
3acc0592b4 DataGrid HeaderCellRender and FooterCellRender events added 2021-12-21 11:14:58 +02:00
yordanov
dc5e24201c Update DataGrid loading indicator color and animation 2021-12-21 10:21:43 +02:00
yordanov
eda8f9ac86 Set tab panel border-radius with respect to TabPosition 2021-12-20 19:53:22 +02:00
Vladimir Enchev
ed19c9c534 Version updated 2021-12-20 16:39:33 +02:00
yordanov
c0ee0195e9 Add TabPosition to Tabs demo 2021-12-20 16:33:02 +02:00
yordanov
ffa35bed94 Add TabPosition styles to Tab Component 2021-12-20 16:31:40 +02:00
yordanov
9442be13f1 Render navigation item link content wrapper when Path is null or empty 2021-12-20 15:10:14 +02:00
Vladimir Enchev
a017803429 Tree AllowCheckChildren will not work when tree children are populated from RadzenTreeLevel settings 2021-12-20 11:51:56 +02:00
Vladimir Enchev
951e88f1c8 Tab component TabPosition property added 2021-12-20 10:19:05 +02:00
Atanas Korchev
de93247c5c ProfileMenu opens behind DataGrid when RadzenLayout is used. 2021-12-19 09:40:00 +02:00
Atanas Korchev
06038bc105 Bar series render in the opposite order. 2021-12-19 09:40:00 +02:00
Vladimir Enchev
43c5975524 Fixed DatePicker will raise exception with chars in time part 2021-12-17 15:01:43 +02:00
Vladimir Enchev
891f183f80 Switch component Toggle method made public and executed on click 2021-12-17 14:51:06 +02:00
yordanov
c126c28fa3 Fix loading panel z-index in sample dashboard 2021-12-17 14:15:16 +02:00
yordanov
fc99e46e0f Update DataList demo 2021-12-17 14:03:22 +02:00
yordanov
9543e10241 Update styles in Tree demos 2021-12-16 18:39:44 +02:00
yordanov
327bc47017 Align icon in treenode label 2021-12-16 16:48:04 +02:00
Vladimir Enchev
96ccc5d4f5 Version updated 2021-12-16 08:49:19 +02:00
Atanas Korchev
eef2b4eb58 Dialog content does not always refresh when DialogService.Refresh is called. 2021-12-15 20:47:55 +02:00
yordanov
26346c8acb Fix boolean filter checkbox background in DataGird 2021-12-15 16:11:19 +02:00
yordanov
565e77ef6d Fix CheckBox tri-state icon 2021-12-15 16:10:13 +02:00
Vladimir Enchev
84506a9340 Fixed virtualized DataGrid will raise exception with FilterTemplate 2021-12-15 11:50:46 +02:00
Vladimir Enchev
25298012f9 DataGrid LoadData will not populate Filters properly 2021-12-15 11:18:05 +02:00
Atanas Korchev
236e2f6d48 Reset the scroll position of RadzenBody after navigation. 2021-12-14 16:11:10 +02:00
yordanov
483283fdd1 Add icons to component groups 2021-12-14 14:34:25 +02:00
Vladimir Enchev
776c2f38f8 Add RadzenLayout. (#312)
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-12-14 09:05:46 +02:00
yordanov
c20cc09959 Update layouts of feedback demos 2021-12-13 16:01:13 +02:00
yordanov
ce7d3f0324 Update layout of validator demos 2021-12-13 16:01:13 +02:00
Vladimir Enchev
55e85dbd74 version updated 2021-12-13 09:29:32 +02:00
Atanas Korchev
4c6f6d8b1c Fix typo in tree data-binding demo. 2021-12-13 08:35:16 +02:00
yordanov
651381c9d7 Style Charts configs 2021-12-10 15:53:34 +02:00
yordanov
146af5cf2d Update Upload demo layout 2021-12-10 15:40:49 +02:00
yordanov
49a7c80423 Update TextArea demo layout 2021-12-10 15:40:49 +02:00
yordanov
e770eb147a Update FileInput demo layout 2021-12-10 15:40:49 +02:00
yordanov
a08802df0a Update Fieldset demo layout 2021-12-10 15:40:49 +02:00
Atanas Korchev
61eba87de6 Do not try to parse null color. 2021-12-10 15:21:11 +02:00
Atanas Korchev
0e0a56ac38 Fixes in the tree guide. 2021-12-10 12:59:51 +02:00
Atanas Korchev
36e6c2fa25 Tree demo source tab fixes. 2021-12-10 12:59:51 +02:00
yordanov
0c157eee69 Update ColorPicker demo layout 2021-12-10 11:49:04 +02:00
yordanov
ba2ac37f6c Update DropDownDataGrid demo layout 2021-12-10 11:48:35 +02:00
yordanov
9a29db8c62 Update DropDown demo layout 2021-12-10 11:48:04 +02:00
yordanov
212ec834c8 Update DatePicker demo layout 2021-12-10 11:47:44 +02:00
Atanas Korchev
bd70d80f81 Do not add upload header without a name. 2021-12-10 09:57:30 +02:00
yordanov
55e2e3463d Format code 2021-12-09 16:46:51 +02:00
yordanov
2e16eba739 Remove typography styles for html elements from base themes 2021-12-09 16:46:51 +02:00
yordanov
35bf66ccf4 Add rz-label CSS class to RadzenLabel component 2021-12-09 16:46:51 +02:00
Vladimir Enchev
ec4679d85c Render optimizations of popups removed 2021-12-09 14:58:11 +02:00
Vladimir Enchev
15c4b0e5eb DropDownDataGrid rendering speed optimized by rendering popup on first click 2021-12-09 11:58:49 +02:00
Vladimir Enchev
5f170f0953 DataGrid rendering speed optimized by rendering advanced filter popups on first click 2021-12-09 11:40:13 +02:00
Vladimir Enchev
07a1e9311b DatePicker rendering speed optimized 2021-12-09 10:22:31 +02:00
Vladimir Enchev
7d1274af4b Version updated 2021-12-09 09:40:55 +02:00
Vladimir Enchev
9d096aed5d Tabs RenderMode.Client will cause exception on browser refresh
Fixed #309
2021-12-09 09:40:19 +02:00
yordanov
8477ad810a Update layouts in demos 2021-12-08 15:02:15 +02:00
Vladimir Enchev
60e3fb6f45 DatePicker will select wrong year when selecting days across years 2021-12-08 10:58:26 +02:00
yordanov
7efb9ec1de Update layouts in demos 2021-12-07 15:37:48 +02:00
Atanas Korchev
70c0a4b9e6 Fix smooth checkbox not working. 2021-12-07 15:26:11 +02:00
yordanov
d9b3474846 Move console below the demo 2021-12-07 10:19:31 +02:00
yordanov
97cb7fc2eb Update console styling 2021-12-07 10:19:31 +02:00
Vladimir Enchev
6394612630 xml comments warnings fixed 2021-12-06 11:35:27 +02:00
Vladimir Enchev
a78df50826 DropDownDataGrid AllowColumnResize property added 2021-12-06 11:21:42 +02:00
yordanov
59c1948e14 Update Steps demo layout 2021-12-06 11:01:47 +02:00
yordanov
e92fa3d615 Update Login page demo layout 2021-12-06 11:01:47 +02:00
Vladimir Enchev
faee5d0276 Version updated 2021-12-06 10:36:41 +02:00
Vladimir Enchev
f2b1e7becc DataGrid Responsive property added 2021-12-06 10:05:35 +02:00
yordanov
5352d55589 Update Tabs demo layout 2021-12-06 09:29:45 +02:00
yordanov
75386e55af Update Splitter demo layout 2021-12-06 09:29:45 +02:00
yordanov
fe2a28d013 Update panel demo layout 2021-12-06 09:29:45 +02:00
Vladimir Enchev
aa2e07d163 DataGrid grouping will check if the group key is null 2021-12-03 16:37:27 +02:00
yordanov
23c1c41415 Panel render text and icon wrapper only if Text or Icon are set 2021-12-03 15:50:59 +02:00
yordanov
8be6988e5b Update DataGrid demos 2021-12-03 14:57:40 +02:00
yordanov
262ccc2f11 Add instrucitons to ContextMenu demo 2021-12-03 14:57:40 +02:00
yordanov
09c3952a0a Update menu demo height 2021-12-03 14:57:40 +02:00
yordanov
ea9c4df4bc Update image demo 2021-12-03 14:57:40 +02:00
yordanov
43c95c24fe Update dialog demos 2021-12-03 14:57:40 +02:00
Vladimir Enchev
21a19dcf89 DataGrid will not go to the previous page if the last item is deleted 2021-12-03 10:45:26 +02:00
Vladimir Enchev
2b6cc3e52d DataGrid StateHasChanged will be executed after every column add 2021-12-02 16:21:59 +02:00
Vladimir Enchev
f639704d6d code removed temporary to avoid recursion 2021-12-02 16:21:37 +02:00
Vladimir Enchev
b93995081e DataGrid will not go to the first page if the last item is deleted on the second page 2021-12-02 16:11:00 +02:00
Atanas Korchev
0dc68b830c Show loading indicator in the LoadData demo. 2021-12-02 15:45:10 +02:00
Vladimir Enchev
5521b90aec DataGrid will show EmptyText/EmptyTemplate only if Count is 0 and Data is not null 2021-12-02 15:15:06 +02:00
yordanov
7f0a13b434 Make Scheduler full width 2021-12-02 13:23:49 +02:00
yordanov
c0e2445439 remove empty row in Pager demo 2021-12-02 13:23:49 +02:00
yordanov
6037b87b52 Update DataGrid column widths across demos 2021-12-02 13:23:49 +02:00
yordanov
b80c5d43e9 Update DataGrid export demo 2021-12-02 13:23:49 +02:00
yordanov
ed258e624d Update layout in cascading dropdowns DataGrid demo 2021-12-02 13:23:49 +02:00
yordanov
e1fd87b251 Update layout in DataGrid inline edit demo 2021-12-02 13:23:48 +02:00
yordanov
092cf6be4f Update DataGrid context menu demo 2021-12-02 13:19:09 +02:00
yordanov
a4286ea2de Update DataGrid master detail demos 2021-12-02 13:19:09 +02:00
yordanov
7ada2de54c Update empty DataGrid demo 2021-12-02 13:19:09 +02:00
yordanov
0f01f513eb Update DataGrid column demos 2021-12-02 13:19:09 +02:00
yordanov
4bebcec778 Reorder radzen banner buttons 2021-12-02 13:19:09 +02:00
Vladimir Enchev
6d2bf8402b demo updated 2021-12-02 09:23:47 +02:00
Vladimir Enchev
674f99d738 Firefox checks for virtualization removed 2021-12-02 09:06:41 +02:00
Roderick Micallef
f12c2d3a7c Update RadzenDataGrid.razor.cs (reordering columns issue) (#300)
* Update RadzenDataGrid.razor.cs

ColumnReorder returns oldIndex from only visible/JS columns, and newIndex from all columns. Proposal is to return indices from all columns for both cases.

* Update RadzenDataGrid.razor.cs

typo fix
2021-12-01 13:41:19 +02:00
Vladimir Enchev
8748b1e122 DataGrid and DropDown virtualization fixed to work properly in Firefox
Fix #275
2021-12-01 13:39:47 +02:00
Vladimir Enchev
b6e4206772 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2021-12-01 10:47:22 +02:00
Vladimir Enchev
2c6224d45e Upload Disabled property added
Fix #299
2021-12-01 10:47:10 +02:00
emumanu
a0c764d87c Fixes Error: System.NotSupportedException: Unable to cast the type 'BlazorRadzenTests.Country' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types. (#298)
In order to fix the problem, we convert the IQueryable to IEnumerable, we perform the cast to IEnumerable<object> and then we call ToList()
2021-12-01 10:38:50 +02:00
Vladimir Enchev
a1f6278711 Version updated 2021-12-01 09:18:35 +02:00
Vladimir Enchev
3ca45f4eef DataGrid IsNull/IsNotNull filtering support added 2021-11-30 11:31:52 +02:00
yordanov
07ff46b98e Update Material icons font 2021-11-29 17:19:13 +02:00
Vladimir Enchev
c73d3fd96b Fixed DataGrid simple filter popup for dates shown at wrong position 2021-11-29 13:17:17 +02:00
Vladimir Enchev
e8594d05cb DatePicker CurrentDateChanged event added 2021-11-29 10:47:11 +02:00
Vladimir Enchev
253db597bd missing articles added 2021-11-29 10:37:32 +02:00
Vladimir Enchev
8058276990 DataGrid column resizing will use integer values only 2021-11-29 10:25:27 +02:00
Vladimir Enchev
1e3f704ffd webcompiler executed directly without tool run 2021-11-29 10:06:35 +02:00
yordanov
871d470c71 Update Card template in DataList and Pager demos 2021-11-26 12:49:12 +02:00
yordanov
fd442bc08c Update spacing in icons demo 2021-11-26 12:49:12 +02:00
Vladimir Enchev
b93499e373 Version updated 2021-11-25 19:19:55 +02:00
yordanov
0a2ddc696b Update Card demo 2021-11-25 15:28:13 +02:00
Atanas Korchev
d8f4020fa8 Split Tree demos to multiple pages. 2021-11-25 12:50:45 +02:00
yordanov
cfbf2c3bed Move standard theme background gradient to <body> 2021-11-25 10:30:34 +02:00
beeterry
3aa41ed16f Added a Focus method on the RadzenNumeric control (#295)
* Added a flag to determine whether the expandable indicator column gets rendered or not.

* ShowExpandableIndicatorColumn renamed to ShowExpandColumn and RadzenDataGridRow fixed to work with the new property

* Added a focus method on the numeric control.

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
Co-authored-by: Brandon Terry <brandon@shipsilo.onmicrosoft.com>
2021-11-25 08:46:59 +02:00
Atanas Korchev
6dae186ed6 Prevent flicker on initial load. 2021-11-24 17:38:56 +02:00
Vladimir Enchev
9b3f0d84a8 Version updated 2021-11-24 12:48:50 +02:00
yordanov
ce1f7280c7 Add background rules to RadzenBody component 2021-11-24 12:40:24 +02:00
Vladimir Enchev
612ef7ef1a CurrentTheme set to standard 2021-11-24 11:50:11 +02:00
Vladimir Enchev
8800303766 Radzen.Blazor version updated 2021-11-24 11:48:20 +02:00
Vladimir Enchev
5dfcc6e851 Standard theme added (#294)
* Add new standard theme

* Update variables in button styles

* Fix border-radius defaults

* Add standard theme to demos

* Update button demo content

* Add pager styles

* Fix button height and vertical-alignment

* Use md-button in pager

* Add animated gradients on button hover and active states

* Fix radiobutton disabled state styles

* Fix checkbox disabled state styles

* Add standard theme checkbox styles

* Set width of busy indicator buttons

* Style slider states

* Add standard theme slider styles

* Add initial standard theme grid styles

* Add standard theme styles for grid filtering

* Remove rz-state-active CSS class from tabs items

* Remove rz-state-active CSS class from accordion headers

* Add standard theme accordion styles

* Set accordion content font-size

* Fix paragraph line-height to inherit -line-height

* Fix ColorPicker OK button to use primary instead of secondary styles

* Update ColorPicker default styles

* Update Input default styles

* Add Input and ColorPicker standard theme styles

* Add standard theme Upload and FileInput styles

* Add standard theme DropDown and ListBox styles

* Add standard theme Charts styles

* Add standard theme Charts and initial PanelMenu styles

* Add standard theme Tooltip styles

* Fix Rating display inline-flex and unify interaction states

* Add standard theme Rating styles

* Add Numeric, Forms, and Fieldset standard theme styles

* Add Standard theme scss variable

* Add Badge standard theme styles

* Remove primary-secondary color dependency in standard theme

* Add DatePicker standard theme styles

* Add Splitter standard theme styles, fix grid filter icon color and body font-size

* Fix Login register button to use secondary button styles

* Add switch box-shadow, fix switch min-width and disabled state

* Add Tree standard theme styles and fix children indentations

* Update Dashboard demo layout

* Add CSS transition to Tree items

* Add Dialog standard theme styles

* Add initial dark sidebar styles to standard theme

* Fix default SplitButton styles and add standard theme styles

* Update SelectBar standard styles

* Add DataList standard theme styles

* Add Card standard theme styles

* Add Steps standard theme styles

* Add Menu standard theme styles

* Add ProfileMenu, Gravatar and Icon standard theme styles

* Add ContextMenu standard theme styles

* Add Panel standard theme styles

* Add Scheduler standard theme styles

* Fix Scheduler Today button margin in standard theme

* Add Editor standard theme styles

* Add dark PanelMenu standard theme styles

* Fix PanelMenu toggle icon opacity

* Fix DropDown item vertical padding

* Fix paddings in dashboard demo

* Fix item paddings in Menu and ProfileMenu

* Fix PanelMenu item paddings and Badge font-size

* Style standard Grid detail template

* Fix horizontal slider height

* Add standard theme tri-state checkbox and radiobutton styles

* Fix hover styles for disabled Dropdown and AutoComplete

* Fix dropdown clear button overlaying dropdown value

* Fix left and right row margin

* Fix FileInput merge conflicts

* Fix icon font-size in current themes

* Fix grid borders in current themes, update standard theme heading and checkbox/radio styles

* Fix default tooltip font-size

* Fix input box-shadow on focus

* Fix border-top-left-radius

* Use primary instead of secondary variables for interaction states

* Add transition variables

* Add transition to menu items

* Add a wrapper in the tree item content.

* Move badge alignment styles to standard theme file

* Fix input disabled state - colors and cursors

* Fix steps number background color and dropdown filter border color

* Fix slider disabled styles

* Fix grid border color, upload colors and editor disabled buttons

* Add Footer and Gauge components, and update variables

* Add default flags, update colorpicker label color and fix pager summary styling

* Fix header height and paragraph line-height

* Add theme background gradient to body

* Add -background

* Add standard-base

Co-authored-by: yordanov <vasil@yordanov.info>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-11-24 11:36:56 +02:00
Vladimir Enchev
2d5703d9d9 Additional CSS classes added to RadzenBody and RadzenSidebar for expanded state 2021-11-23 15:56:17 +02:00
Vladimir Enchev
796a4753c9 exception fixed and version updated 2021-11-23 10:36:20 +02:00
Vladimir Enchev
69cbeaaa1f version updated 2021-11-23 10:18:17 +02:00
Vladimir Enchev
10e37a2f8e DataGrid "rz-datatable-edit" CSS class added to edited rows
Fix #290
2021-11-23 08:42:10 +02:00
Vladimir Enchev
416635020c Mask CharacterPattern logic fixed
Fix #291
2021-11-23 08:36:37 +02:00
Vladimir Enchev
36e9810f43 Radzen.Blazor version updated 2021-11-22 12:18:01 +02:00
beeterry
ecd3699620 Expandable Indicator Column Visibility Flag (#288)
* Added a flag to determine whether the expandable indicator column gets rendered or not.

* ShowExpandableIndicatorColumn renamed to ShowExpandColumn and RadzenDataGridRow fixed to work with the new property

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2021-11-22 12:17:02 +02:00
Dennis Tjassens
cb63d3689d Update RadzenTooltip.razor (#289)
I believe the '@' shouldnt be there and if you cast the text to markupstring you dont need the renderfragment implementation? This would mean the overload from the tooltipservice should also be removed of course :-) I stumbled upon this because I implemented your tooltip in my base viewmodel and didnt want to start buildiing a fragment tree.
2021-11-22 11:02:13 +02:00
Vladimir Enchev
d69e7ae872 DataGrid OData support added for multiple values filter 2021-11-19 12:36:34 +02:00
Atanas Korchev
33dabab5a6 Implement Trim property. 2021-11-19 10:10:01 +02:00
Vladimir Enchev
c8dec26d15 Fixed DataGrid EmptyText truncated
Fix #286
2021-11-19 09:45:18 +02:00
Vladimir Enchev
cce77d00ff comment updated 2021-11-19 09:26:38 +02:00
Vladimir Enchev
7853d457a1 Mask CharacterPattern property added as positive alternative of Pattern 2021-11-19 09:25:38 +02:00
Vladimir Enchev
fd9318c127 version updated 2021-11-18 17:23:21 +02:00
Atanas Korchev
8bd9f6cb4a Picking a month closes the datepicker. 2021-11-18 17:16:45 +02:00
gagabu
c3aeb82137 add Kind parameter for DateTime in RadzenDatePicker (#284)
Co-authored-by: gagabu <bookuk@gmail.com>
2021-11-18 16:23:36 +02:00
Vladimir Enchev
322d4ab8a1 DataGrid custom filtering by multiple values support added 2021-11-18 16:02:26 +02:00
OlgaV23
1fa6d61468 Some spelling fixes (#283) 2021-11-18 15:28:27 +02:00
Andrei Ciudacov
bf15621d24 datagrid.md updated (#281)
Added hint for those who struggle with DataGrid not being updated after async call to LoadData.
2021-11-16 11:01:08 +02:00
Vladimir Enchev
39ce0abfe5 version updated 2021-11-15 10:52:54 +02:00
Vladimir Enchev
5ee754f82f Gravatar fixed for .NET 5 and 6 WASM 2021-11-15 10:14:04 +02:00
Atanas Korchev
ff7ffcbacb Prevent HtmlEditor tools from getting keyboard focus. Closes #276. 2021-11-11 18:55:29 +02:00
Atanas Korchev
0d02b443e7 Close popups on mousedown instead of click. Fixes ##274. 2021-11-11 12:38:45 +02:00
Vladimir Enchev
4ddae3d3ed version up and demos updated to .net 6 2021-11-11 08:46:08 +02:00
Vladimir Enchev
1194a3a231 DataGrid GroupFooterTemplate position fixed
Fix #271
2021-11-10 20:25:27 +02:00
Atanas Korchev
612cfc5bfc Stop navigating when the toggle icon of a RadzenPanelMenuItem is clicked. 2021-11-08 19:14:01 +02:00
Vladimir Enchev
0340fcd8bf DropDownDataGrid ShowPagingSummary and PagingSummaryFormat added 2021-11-08 10:46:25 +02:00
Vladimir Enchev
4bb4a2836c PagingSummaryFormat added for DataGrid paging API demo 2021-11-08 10:43:35 +02:00
Vladimir Enchev
8d9da9f6b2 Radzen.Blazor updated 2021-11-04 08:34:32 +02:00
Vladimir Enchev
faf306ab83 version updated 2021-11-04 08:34:09 +02:00
Atanas Korchev
fcaa13e4c4 Fix XML comment warnings. 2021-11-02 18:48:58 +02:00
Atanas Korchev
4987cc92a1 Add missing await. 2021-11-02 18:45:58 +02:00
Atanas Korchev
fe9ad58989 Detect changes in the count of the series data and refresh. 2021-11-02 18:42:40 +02:00
Vladimir Enchev
95470804f1 code improved 2021-11-02 13:20:52 +02:00
Vladimir Enchev
300e2aabba Tabs SelectedIndex not working properly in RenderMode.Client 2021-11-02 12:59:52 +02:00
Vladimir Enchev
f9f917f007 Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2021-11-01 11:05:51 +02:00
Vladimir Enchev
dbb49cac6c DataGrid CellContextMenu event added 2021-11-01 11:05:41 +02:00
Atanas Korchev
5540c1855f Implement SlotRender event. 2021-11-01 10:57:11 +02:00
Atanas Korchev
7d64e08093 Delete erroneous toc file. 2021-11-01 09:25:40 +02:00
Vladimir Enchev
4dafd8c3ff version updated 2021-11-01 09:17:36 +02:00
Vladimir Enchev
b6f65c40cf sln updated 2021-11-01 09:15:28 +02:00
yordanov
07e61cd1d3 Fix TOC alignment on small screens 2021-10-29 16:56:51 +03:00
yordanov
c12c496058 Fix width of content images on smaller screens 2021-10-29 16:56:51 +03:00
Atanas Korchev
4a5db41302 Add documentation contribution guidelines. 2021-10-29 15:46:32 +03:00
Atanas Korchev
21f269593a Update documentation links. 2021-10-29 15:31:42 +03:00
yordanov
56a14ecd77 Fix h1 font-size and main-nav background 2021-10-29 15:09:43 +03:00
Vladimir Enchev
a2c770d798 article fixed 2021-10-29 15:09:43 +03:00
Vladimir Enchev
31351837a7 accordion added 2021-10-29 15:09:43 +03:00
yordanov
bc9a0f749b Fix search position in navbar 2021-10-29 15:09:43 +03:00
yordanov
e8d590c622 Update radzen Blazor logo 2021-10-29 15:09:43 +03:00
yordanov
5cb7314b56 Fix toc.yml 2021-10-29 15:09:43 +03:00
yordanov
b724e728d9 Add search autofocus and fix navbar searhc padding 2021-10-29 15:09:43 +03:00
Atanas Korchev
c686014204 ArcGauge and RadialGauge articles. 2021-10-29 15:09:43 +03:00
yordanov
b6534fd91d Update logo 2021-10-29 15:09:43 +03:00
yordanov
5a964a1dd5 Fix transition styles for main nav links 2021-10-29 15:09:43 +03:00
yordanov
1d290e97b8 Add links to component demos, radzen website and fix responsive issues 2021-10-29 15:09:43 +03:00
yordanov
9f68cdbd6e Rename search input placeholders 2021-10-29 15:09:43 +03:00
yordanov
bb3269646d Update alert heading and background styles 2021-10-29 15:09:43 +03:00
yordanov
abba89bcad Add Radzen banner to the footer and update content styles 2021-10-29 15:09:43 +03:00
yordanov
352642c93a Rename Articles to Guides 2021-10-29 15:09:43 +03:00
yordanov
fb8f5120e0 Update code highlight colors 2021-10-29 15:09:43 +03:00
yordanov
c9bcf947c6 Update content styles and layout 2021-10-29 15:09:43 +03:00
Vladimir Enchev
7100612187 Splitter added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
b1d1022930 Tabs and Steps added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
1c39460172 SSRSViewer added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
ed12e59e67 Pager added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
30563b19ef Upload added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
79f1ee85c0 SplitButton added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
12d38bc8fc Slider added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
70b15f5f9a ProgressBar added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
207744b628 Rating added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
f07e0868e5 Notification added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
38bf3d0d34 Tooltip added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
a0e5bd4769 Login added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
601dec9768 Badge added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
63cb5ee909 Link and Label added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
e3d8bd0242 menus added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
489e334acb Accordion added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
8c9069b765 Gravatar added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
1066421df5 Icon and Image added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
6535dc3e66 Numeric added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
05d75eb9e2 Mask added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
7dc5aaa7a4 ListBox added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
08a4c8f6ad SelectBar added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
f8fb029d95 Password and Switch added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
053cce5f51 TextBox and TextArea added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
4afbe84391 FileInput added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
abd87c42ca RadioBoxList added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
50876fee39 Fieldset and Panel articles added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
56ca97d74e DropDown and DropDownDataGrid articles added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
32b90262ed article updated 2021-10-29 15:09:43 +03:00
Vladimir Enchev
e3db36613e dialog article updated 2021-10-29 15:09:43 +03:00
Vladimir Enchev
b96299e3d0 ContextMenu article added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
9dc06419cf article fixed 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d9ffcdf59b DataList updated 2021-10-29 15:09:43 +03:00
Vladimir Enchev
4f4d7a19f1 datagrid updated 2021-10-29 15:09:43 +03:00
yordanov
b65ede4f4f Add docs homepage content and styles 2021-10-29 15:09:43 +03:00
Atanas Korchev
ff344082c6 Scheduler article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
387684445e RequiredValidator article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
9ee9de7695 RegexValidator page. 2021-10-29 15:09:43 +03:00
Atanas Korchev
fdc7a04141 NumericRangeValidator article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
399a51b2bb LengthValidator article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
5c146c0ba1 EmailValidator article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
f11196975b CompareValidator article. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
728a2e7276 autocomplete restored 2021-10-29 15:09:43 +03:00
Vladimir Enchev
f3ac621bbf datagrid article updated 2021-10-29 15:09:43 +03:00
Atanas Korchev
1e67e6f2af Update the template form article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
fc3e915da6 Add GA. 2021-10-29 15:09:43 +03:00
Atanas Korchev
e8830d2837 Remove dashes from article names. 2021-10-29 15:09:43 +03:00
Atanas Korchev
ff45b12b13 Update documentation links. 2021-10-29 15:09:43 +03:00
Atanas Korchev
77ea27f340 Update documentation links. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
9086a07f69 articles updated 2021-10-29 15:09:43 +03:00
Atanas Korchev
69f06c2b12 Document common component properties. 2021-10-29 15:09:43 +03:00
Atanas Korchev
5737093e66 Button article improvements. 2021-10-29 15:09:43 +03:00
Atanas Korchev
b5ebec5167 Use article instead of tutorial and guide. 2021-10-29 15:09:43 +03:00
Atanas Korchev
56d519a780 Nest data-binding sectioins. 2021-10-29 15:09:43 +03:00
Atanas Korchev
0805130582 Tree tutorial. 2021-10-29 15:09:43 +03:00
Atanas Korchev
9ef6380f0a HtmlEditor tutorial. 2021-10-29 15:09:43 +03:00
Atanas Korchev
a669a7ee75 Chart tutorial. 2021-10-29 15:09:43 +03:00
Atanas Korchev
e89d2006f5 Fix the TOC. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
a17522095c articles added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
61f4b7c1e5 card and html components removed 2021-10-29 15:09:43 +03:00
Vladimir Enchev
104f434f57 AutoComplete added 2021-10-29 15:09:43 +03:00
Atanas Korchev
e6d03ebc9a Add sitemap generation. 2021-10-29 15:09:43 +03:00
Atanas Korchev
13b34a8c50 Add dialog, notification and tooltip setup. 2021-10-29 15:09:43 +03:00
Atanas Korchev
9b541ce614 Finish context menu setup. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
391a7da7da toc fixed 2021-10-29 15:09:43 +03:00
Atanas Korchev
fd152df645 Context menu setup. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
1bfdfb1a24 component articles added 2021-10-29 15:09:43 +03:00
Atanas Korchev
0d93cbf797 Add use component article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
aaab58e9b2 Add getting started installation article. 2021-10-29 15:09:43 +03:00
Atanas Korchev
af48ab19d6 Add tutorial intro. 2021-10-29 15:09:43 +03:00
Atanas Korchev
d5fd2710fc Allow default documents. 2021-10-29 15:09:43 +03:00
Atanas Korchev
93becd5a98 Update TOC and API index. 2021-10-29 15:09:43 +03:00
Atanas Korchev
4e6eb6c53a Remove automatic descriptions. 2021-10-29 15:09:43 +03:00
Atanas Korchev
85ac31af36 Add missing documentation. 2021-10-29 15:09:43 +03:00
Atanas Korchev
594657acd0 Inherit common documentation. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
a1bfb0da5b xml comment added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
9742ffe769 missing xml comments added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
a9ddb52c5d more xml comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
5babbe19c3 comment removed 2021-10-29 15:09:43 +03:00
Atanas Korchev
fd8bab6348 Remove XML comment warnings. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
e6764c1bdf more xml comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d998f87099 more xml comments imoroved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
e90e035825 more xml comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
3817597229 xml comments improved 2021-10-29 15:09:43 +03:00
yordanov
d97da4d532 Add initial docs layout and styles 2021-10-29 15:09:43 +03:00
Vladimir Enchev
1e2b6fed14 Notification summary fixed 2021-10-29 15:09:43 +03:00
Vladimir Enchev
31cd1cb5e8 NotificationService example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d567e95f7f ContextMenuService example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
354530ba66 TooltipService example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
c532ecbfb8 DialogService example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
6e5a887fdb RadzenUpload example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
2632b0ad09 Steps and Tabs examples added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
8577330e27 example fixed 2021-10-29 15:09:43 +03:00
Vladimir Enchev
996be526fb RadzenSplitButton example added 2021-10-29 15:09:43 +03:00
Atanas Korchev
e3146abae1 HtmlEditor API reference. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
7f756c5028 examples added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
94e570917a various components examples added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
5c11fb87c2 RadzenLogin example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
67a0e4bf28 RadzenListBox example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
c4485fe742 RadzenLink example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
33f56831b7 RadzenLabel example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
cc467c1b74 RadzenImage and RadzenIcon examples added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
ea3271b49e RadzenGravatar example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
3eeddfdd85 RadzenGoogleMap example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
7df7e7c9e9 RadzenFileInput example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
c5a20a334e RadzenFieldset example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
3c5e9459de RadzenDropDownDataGrid example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
77f99cec6f RadzenDropDown example added 2021-10-29 15:09:43 +03:00
Vladimir Enchev
39d6384b15 RadzenDatePicker example added 2021-10-29 15:09:43 +03:00
Atanas Korchev
1115558d0d RadzenTicks API reference. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d6d1226a6c RadzenDataList example added 2021-10-29 15:09:43 +03:00
Atanas Korchev
7ecff3bd9c Fix XML comment errors. 2021-10-29 15:09:43 +03:00
Atanas Korchev
98bf800d78 Tree API reference 2021-10-29 15:09:43 +03:00
Vladimir Enchev
bd897b67d3 RadzenDataGrid example added 2021-10-29 15:09:43 +03:00
Atanas Korchev
a3b5c6b716 TemplateForm API reference. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
c67d6e8474 RadzenContextMenu example added 2021-10-29 15:09:43 +03:00
Atanas Korchev
29d8800907 Validators API reference. 2021-10-29 15:09:43 +03:00
Atanas Korchev
2a769dd43e Chart API referennce. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
cdfb6484b8 api examples added 2021-10-29 15:09:43 +03:00
Atanas Korchev
4f3eacd322 RadzenComponent API reference. 2021-10-29 15:09:43 +03:00
Atanas Korchev
9690659278 Scheduler API reference. 2021-10-29 15:09:43 +03:00
Atanas Korchev
da009b5130 Scheduler API reference. 2021-10-29 15:09:43 +03:00
Atanas Korchev
1bebc5baee Documentation of common types. 2021-10-29 15:09:43 +03:00
Vladimir Enchev
199405cb56 more comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
45fcde1d73 more comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
b12eca2460 more comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
092cd39ed7 more comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
b349d12326 various comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
fe375548a5 various components comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
2a771ab203 RadzenDropDown and RadzenDropDownDataGrid comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d90e54849a RadzenDatePicker and RadzenDataList comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
f85e3ce24b RadzenDataGridColumn comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
61f667622a RadzenDataGrid comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
d60e2abcce RadzenContextMenu comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
ceec364360 RadzenContentContainer and RadzenContent comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
fffdc70a5c RadzenCompareValidator comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
b94136e99c RadzenColorPickerItem comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
7257f13b9b RadzenColorPicker comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
e90ad0afdc RadzenCheckBoxListItem comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
67e44a2d3c RadzenCheckBoxList comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
01c199b0d0 RadzenCard and RadzenCheckBox comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
4e53ea3ee5 RadzenButton comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
28a06a16eb RadzenBody comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
8d5d74dc48 child content comments improved 2021-10-29 15:09:43 +03:00
Vladimir Enchev
209e192942 Accordion comments improved 2021-10-29 15:09:43 +03:00
Atanas Korchev
515c15a662 Move Dockerfile to top level. Run docfx. 2021-10-29 15:09:43 +03:00
Atanas Korchev
54d90a1062 Remove toc.yml from git. Add api/index.md. 2021-10-29 15:09:43 +03:00
Atanas Korchev
c5a6776ccc Add filter to exclude namespaces and types. 2021-10-29 15:09:43 +03:00
Atanas Korchev
8cbc22bb29 Serve documentation without .html extension. 2021-10-29 15:09:43 +03:00
Atanas Korchev
2b17edc82d Enable search. 2021-10-29 15:09:43 +03:00
Atanas Korchev
1f79572c07 Add docfx. 2021-10-29 15:09:43 +03:00
Atanas Korchev
d15ddb5923 Move the @code section of RadzenLabel to a .cs file in order to get XML documentation working. 2021-10-29 15:09:43 +03:00
Atanas Korchev
25fed73b74 Enable xml documentation. 2021-10-29 15:09:43 +03:00
viordash
82f7908384 Pager summary (#258)
* RadzenPager. unify similar code for disabled/enabled buttons

* RadzenPager. unify similar code for active buttons

* WIP. prepare for show summary in RadzenPager

* fix after merge. move ShowSummary to partial class

* fix font color for dark theme

* output real values to a summary

* align summary position

* create test of rendering summary

* rename parameter && propagate PageShowSummary to paged data components

* demo for pager summary

* to prevent UI BC set PageShowSummary to default false

* Paging summary format added to enable localization

Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2021-10-29 10:16:36 +03:00
Atanas Korchev
ec294cd951 Make RadzenHtmlEditor buttons not focusable via tabbing. 2021-10-29 08:19:42 +03:00
Vladimir Enchev
2fba579edd DatePicker should not reset time when changing the day 2021-10-28 10:01:04 +03:00
Vladimir Enchev
efe671ceff Version updated 2021-10-28 08:47:48 +03:00
Vladimir Enchev
169a014437 DatePicker will update our to 23 when attempt to set lower than 0 2021-10-26 09:13:26 +03:00
Vladimir Enchev
41a14d440f DatePicker cannot update time 2021-10-26 08:19:22 +03:00
Vladimir Enchev
f120bf56b0 DatePicker current date not reset when Value is set 2021-10-25 20:00:08 +03:00
Vladimir Enchev
d5dc89004e Version updated 2021-10-21 10:39:29 +03:00
Vladimir Enchev
a60d83f588 DatePicker async voids reworked 2021-10-21 09:29:03 +03:00
Vladimir Enchev
e332a9bd71 DatePicker month/year selection fixed 2021-10-21 09:25:49 +03:00
Vladimir Enchev
b8ec9e1935 DatePicker changing months should not show a different selected date than is actually selected
Fix #256
2021-10-21 09:22:36 +03:00
Vladimir Enchev
2cea42184b FIxed DatePicker TimeOnly with ShowTimeOkButton false will not update after change 2021-10-21 09:08:49 +03:00
Atanas Korchev
981256287a Clicking ProfileMenu items does not close it. 2021-10-20 13:44:32 +03:00
Vladimir Enchev
c2b84a6de4 Sidebar with DataGrid frozen columns fixed 2021-10-19 12:46:12 +03:00
Vladimir Enchev
5fea7316bd version updated 2021-10-19 09:44:29 +03:00
Vladimir Enchev
f3ef9224ef DatePicker will select wrong month when choosing date from previous/next month 2021-10-19 09:44:19 +03:00
Atanas Korchev
92c785746e RadzenCheckBox does not post its value. 2021-10-18 09:21:18 +03:00
Vladimir Enchev
b10ba79056 version updated 2021-10-18 09:08:01 +03:00
Vladimir Enchev
d73f29941d Fixed DropDown items count whith LoadData and enabled virtualization 2021-10-17 16:41:48 +03:00
Atanas Korchev
b0fccf1d8f EmailValidator should not validate empty strings. 2021-10-14 20:05:22 +03:00
Vladimir Enchev
2c93f6038e DataGrid sorting and grouping will raise exception when using nested properties with null 2021-10-14 16:05:37 +03:00
Atanas Korchev
588e2c71f1 Documentation of common types. 2021-10-14 12:17:16 +03:00
Vladimir Enchev
8aaaed0f3c Fixed DatePicker month and year will be reset to selected value 2021-10-14 09:24:29 +03:00
Vladimir Enchev
0df1041339 version updated 2021-10-14 08:54:27 +03:00
Vladimir Enchev
5470222496 Fixed moving a slider handle to the left/right does not result in the minimum/maximum value
Fix #252
2021-10-13 15:18:35 +03:00
Vladimir Enchev
b86d43d829 Fixed website can be moved while slider handle is moved
Fix #251
2021-10-13 15:02:07 +03:00
Brett Caswell
df96cb890b ensure async-await task completion follows StateHasChanged calls in Chart -- implementing asynchronous phasing to ensure state changes are rendered; call to DisplayTooltip in refresh conditionally; remove DisplayTooltip from CartesianSeries SetParametersAsync
resolves 246
2021-10-13 12:50:31 +03:00
Vladimir Enchev
db89739e6d DatePicker should not update selected date on navigation
Fixed #249
2021-10-13 09:57:27 +03:00
Viktor Geringer
02134ceaf8 Add functionality to close a dialog on clicking outside (#248)
* CloseDialogOnOverlayClick property added to DialogOptions

* fix typo
2021-10-12 15:02:19 +03:00
WaldiTUD
958caabd8e Clear or revert to previous date when entered disabled date (#247)
* Prohibit to enter disabled dates in DatePicker

* Revert "Prohibit to enter disabled dates in DatePicker"

This reverts commit 3c45c48b02.

* Prohibit to enter disabled dates in DatePicker

* Clear or revert to previous date when entered disabled date
2021-10-12 09:53:51 +03:00
Vladimir Enchev
9406bcc2e5 version updated 2021-10-11 09:58:30 +03:00
Atanas Korchev
b19dbc9ffd Changing the Alpha value of the ColorPicker throws exception when the current culture uses "," as decimal separator. 2021-10-08 13:19:29 +03:00
Vladimir Enchev
021dd04707 DataGrid GroupFootersAlwaysVisible property added 2021-10-08 11:25:35 +03:00
Vladimir Enchev
fc43cc703e Hide group panel 2021-10-08 10:46:40 +03:00
Vladimir Enchev
a99e99f70f Radzen.Blazor updated 2021-10-07 13:09:03 +03:00
Vladimir Enchev
0051cba426 Version updated 2021-10-07 13:06:10 +03:00
Vladimir Enchev
6aabb3d6df more components reworked with partial classes 2021-10-07 12:03:06 +03:00
Vladimir Enchev
16cca6572c XML comments added 2021-10-07 11:35:29 +03:00
Vladimir Enchev
af11ca49fe RadzenUpload reworked with partial class 2021-10-07 11:13:48 +03:00
Vladimir Enchev
0e07147d07 RadzenTreeLevel reworked with class 2021-10-07 11:12:04 +03:00
Vladimir Enchev
8e5573b8f9 RadzenTree reworked with partial class 2021-10-07 11:11:02 +03:00
Vladimir Enchev
e7fc1844a2 RadzenTicks reworked with class 2021-10-07 11:07:01 +03:00
Vladimir Enchev
4759724d2b RadzenTextBox reworked with partial class 2021-10-07 11:05:56 +03:00
Vladimir Enchev
96086c1b6e RadzenTextArea reworked with partial class 2021-10-07 11:04:41 +03:00
Vladimir Enchev
fd63f74b98 RadzenTabs reworked with partial class 2021-10-07 11:03:33 +03:00
Vladimir Enchev
d7e6a145e9 RadzenSwitch reworked with partial class 2021-10-07 10:59:01 +03:00
Vladimir Enchev
6a3b449e46 RadzenSteps reworked with partial class 2021-10-07 10:56:09 +03:00
Vladimir Enchev
a2a9124f07 RadzenSSRSViewer reworked with partial class 2021-10-07 10:53:06 +03:00
Vladimir Enchev
a18a959ef6 RadzenSplitter reworked with partial class 2021-10-07 10:50:34 +03:00
Vladimir Enchev
444b3c0af4 RadzenSplitButton reworked with partial class 2021-10-07 10:45:50 +03:00
Vladimir Enchev
eae2fe427d RadzenSlider reworked with partial class 2021-10-07 10:43:27 +03:00
Vladimir Enchev
970bf46d8c RadzenSidebar reworked with partial class 2021-10-07 10:41:01 +03:00
Vladimir Enchev
0d0ebeeacb RadzenSelectBar reworked with partial class 2021-10-07 10:38:56 +03:00
Vladimir Enchev
c8a9e3e443 RadzenScheduler reworked with partial class 2021-10-07 10:35:50 +03:00
Vladimir Enchev
9bbd2fe078 RadzenRating reworked with partial class 2021-10-07 10:32:09 +03:00
Vladimir Enchev
25b2bb9e30 RadzenRadioButtonList reworked with partial class 2021-10-07 10:30:35 +03:00
Vladimir Enchev
7dda099a50 RadzenRadialGauge reworked with partial class 2021-10-07 10:27:21 +03:00
Vladimir Enchev
9f9376e7bf RadzenProgressBar reworked with partial class 2021-10-07 10:21:35 +03:00
Vladimir Enchev
4549f271a2 RadzenProfileMenu reworked with partial class 2021-10-07 10:20:23 +03:00
Vladimir Enchev
ca4ef952c8 RadzenPieSeries reworked with partial class 2021-10-07 10:17:55 +03:00
Vladimir Enchev
92c2b2566b RadzenPassword reworked with partial class 2021-10-07 10:14:50 +03:00
Vladimir Enchev
4a7d5938f1 RadzenPanelMenu reworked with partial class 2021-10-07 10:13:32 +03:00
Vladimir Enchev
e50eb147f4 RadzenPanel reworked with partial class 2021-10-07 10:10:30 +03:00
Vladimir Enchev
e0eedae8a0 RadzenPager reworked with partial class 2021-10-07 10:08:48 +03:00
Vladimir Enchev
5ac49e58f6 RadzenNumeric reworked with partial class 2021-10-07 10:07:21 +03:00
Vladimir Enchev
3b65dd9765 RadzenMenuItem reworked with partial class 2021-10-07 10:04:54 +03:00
Vladimir Enchev
d882c26c03 RadzenMenu reworked with partial class 2021-10-07 10:03:39 +03:00
Vladimir Enchev
319d8bdde4 RadzenMask reworked with partial class 2021-10-07 10:02:29 +03:00
Vladimir Enchev
a8c065cfc8 RadzenMarkers reworked with code instead razor 2021-10-07 10:01:15 +03:00
Vladimir Enchev
f57b8d0eec RadzenLogin reworked with partial class 2021-10-07 10:00:01 +03:00
Vladimir Enchev
bafc8ab28d RadzenListBox reworked with partial class 2021-10-07 09:58:34 +03:00
Vladimir Enchev
48179125f4 RadzenLink reworked with partial class 2021-10-07 09:54:04 +03:00
Vladimir Enchev
6468c548e3 RadzenLineSeries reworked with partial class 2021-10-07 09:52:52 +03:00
Vladimir Enchev
e165440623 RadzenLegend reworked with code 2021-10-07 09:50:18 +03:00
Vladimir Enchev
2e1936df52 RadzenLabel reworked with partial class 2021-10-07 09:48:24 +03:00
Vladimir Enchev
1a52d98966 RadzenImage reworked with partial class 2021-10-07 09:47:17 +03:00
Vladimir Enchev
05ce9531d1 RadzenIcon reworked with partial class 2021-10-07 09:45:51 +03:00
Vladimir Enchev
20e400b101 RadzenHtmlEditor reworked with partial class 2021-10-07 09:44:29 +03:00
Vladimir Enchev
123f907f83 RadzenHtml reworked with partial class 2021-10-07 09:41:16 +03:00
Vladimir Enchev
dd91ece92a RadzenHeading reworked with partial class 2021-10-07 09:40:00 +03:00
Vladimir Enchev
462f555d5f RadzenHeader reworked with partial class 2021-10-07 09:38:36 +03:00
Vladimir Enchev
b05d419b2f RadzenGravatar reworked with partial class 2021-10-07 09:37:21 +03:00
Vladimir Enchev
e435b772f3 RadzenGoogleMap reworked with partial class 2021-10-07 09:35:40 +03:00
Vladimir Enchev
ce345a3c71 RadzenFooter reworked with partial class 2021-10-07 09:32:15 +03:00
Vladimir Enchev
110e3f2e8b RadzenFileInput reworked with partial class 2021-10-07 09:30:04 +03:00
Vladimir Enchev
83a8ebff7e RadzenFieldset reworked with partial class 2021-10-07 09:27:28 +03:00
Vladimir Enchev
ff7141fa43 RadzenDropDownDataGrid reworked with partial class 2021-10-07 09:24:23 +03:00
Vladimir Enchev
5f4cc07a98 DropDown reworked with partial class 2021-10-07 09:20:12 +03:00
Vladimir Enchev
d855c7d3d2 RadzenDatePicker reworked with partial class 2021-10-07 09:15:37 +03:00
Vladimir Enchev
bd145f8c3a RadzenDataList reworked with partial class 2021-10-07 09:09:08 +03:00
Vladimir Enchev
99a1e4a557 RadzenDataGrid reworked with partial class 2021-10-06 12:46:16 +03:00
Vladimir Enchev
cbaa5c8228 RadzenContextMenu with partial class 2021-10-06 12:39:10 +03:00
Vladimir Enchev
cc767d3964 RadzenContentContainer reworked with partial class 2021-10-06 12:36:13 +03:00
Vladimir Enchev
8320681e92 RadzenContent reworked with partial class 2021-10-06 12:34:17 +03:00
Vladimir Enchev
c01b333d77 RadzenColumnSeries reworked with partial class 2021-10-06 12:30:04 +03:00
Vladimir Enchev
bbdba2b7c5 RadzenColumnOptions reworked with partial class 2021-10-06 12:25:34 +03:00
Vladimir Enchev
db170b67ad RadzenColorPicker reworked with partial class 2021-10-06 12:23:54 +03:00
Vladimir Enchev
dd8077d7e2 RadzenCheckBoxList reworked with partial class 2021-10-06 12:19:21 +03:00
Vladimir Enchev
006ee37e0a RadzenCheckBox reworked with partial class 2021-10-06 12:13:55 +03:00
Vladimir Enchev
d607fb053a RadzenChartTooltipOptions reworked with partial class 2021-10-06 12:11:49 +03:00
Vladimir Enchev
1db607822b RadzenChart reworked with partial class 2021-10-06 12:08:38 +03:00
Vladimir Enchev
72c07c4cd4 RadzenCard reworked with partial class 2021-10-06 12:00:41 +03:00
Vladimir Enchev
51ede1c550 RadzenButton reworked with partial class 2021-10-06 11:49:25 +03:00
Vladimir Enchev
6275df77a3 RadzenBody reworked with partial class 2021-10-06 11:44:06 +03:00
Vladimir Enchev
0d5f00117d RadzenBadge reworked with partial class 2021-10-06 11:38:43 +03:00
Vladimir Enchev
b6bc3687ae RadzenAutoComplete reworked with partial class 2021-10-06 11:33:43 +03:00
Vladimir Enchev
e18f13c315 Accordion reworked with partial class 2021-10-06 11:24:30 +03:00
Vladimir Enchev
f41d2da14b Fixed DataGrid odd/even row styles with virtualization 2021-10-06 10:42:31 +03:00
Brett Caswell
1f8ebb83f5 Add RadioButtonList DisabledProperty & VisibleProperty parameters and support for data parameter field binding (#244)
* adding tryGet pattern to support optional/null properties in data item parameter

* support Disabled and Visible Data Property on RadioButtonList and add Set methods on RadioButtonListItem

* update two examples to demonstrate using foreach on data in Items RenderFragment and using added data properties

* add OnChange to one added example; update OnChange text to reflect example header text

* minor refactor to handle scope, and to reduce variable declarations and assignments

* flipped the logic with refactor
2021-10-05 15:10:56 +03:00
Vladimir Enchev
cf5af654e1 Radzen.Blazor version updated 2021-10-05 10:48:13 +03:00
Vladimir Enchev
5afbad5616 version updated 2021-10-05 10:46:20 +03:00
Vladimir Enchev
0f4360fa63 various comments added 2021-10-05 10:45:48 +03:00
Vladimir Enchev
39c9362a41 Slider support for negative values added (#242)
* Handle negative value (simple slider).

* Range slider with negative values

Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-10-04 16:35:52 +03:00
Atanas Korchev
3e08481516 Implement SeriesClick. 2021-10-04 11:34:45 +03:00
Creator512
90f9278b69 Bugfix ColorPicker wrong CultureInfo 2021-10-04 10:34:29 +03:00
Vladimir Enchev
6741e69b08 Dialog render on drag improved 2021-10-01 10:55:10 +03:00
Vladimir Enchev
88b4a75f95 version updated 2021-09-30 12:48:48 +03:00
Vladimir Enchev
1c3831aa72 Radzen.Blazor version updated 2021-09-30 12:47:31 +03:00
Vladimir Enchev
38d3be5354 Resized Dialog width/height not persisted after drag 2021-09-30 12:47:21 +03:00
Vladimir Enchev
d495c081cb Radzen.Blazor version updated 2021-09-30 10:23:37 +03:00
Vladimir Enchev
3a5a014590 Dialog Draggable option added 2021-09-29 11:44:27 +03:00
Vladimir Enchev
6f94bc4b1a DataGrid odd/even row style will not be applied if virtualization is enabled 2021-09-29 09:12:57 +03:00
Vladimir Enchev
11da788756 DropDown with filtering closed immediately when open on Android
Fix #233
2021-09-29 09:00:13 +03:00
Vladimir Enchev
3a5c59d22d Resizable property added to DialogOptions 2021-09-28 15:31:25 +03:00
Atanas Korchev
952f02ebc9 Use Culture instead of DateTimeInfo.CurrentInfo. 2021-09-28 12:48:56 +03:00
Javier Campos
4c649ef750 Remove GetComponentCulture() and replace it with direct property getter 2021-09-28 12:48:56 +03:00
Javier Campos
2fe12c664f Removed unused usings 2021-09-28 12:48:56 +03:00
Javier Campos
fc0a28cd20 Removed ToCultureString and related usages on TextProperties 2021-09-28 12:48:56 +03:00
Javier Campos
7bf3d4c69f Add culture and default culture to base components and use the culture in default templates 2021-09-28 12:48:56 +03:00
Atanas Korchev
4b43a696be Improve the SingleExpand implementation to support more cases. 2021-09-28 11:23:57 +03:00
Atanas Korchev
fc6f0b7da9 RadzenTreeItem uses ClassList. 2021-09-28 10:08:32 +03:00
Atanas Korchev
386a1769ba Add SingleExpand property to RadzenTreeView. 2021-09-28 10:02:32 +03:00
Atanas Korchev
48415a4d87 Avoid manual capitalization. 2021-09-27 16:13:53 +03:00
Daniel Sör
52db213cea RadzenScheduler Culture override support 2021-09-27 16:13:53 +03:00
Vladimir Enchev
5a8f26fb5b Version updated 2021-09-27 14:45:06 +03:00
Vladimir Enchev
84ec51da54 Fixed #225 2021-09-27 14:38:41 +03:00
Atanas Korchev
5d64fbd9af RadzenRadioButtonList uses ClassList and GetClassList. 2021-09-25 15:12:53 +03:00
Atanas Korchev
514c12db0c RadzenListBox uses GetClassList. 2021-09-25 15:05:29 +03:00
Atanas Korchev
0bc593c3df RadzenRating uses GetClassList. 2021-09-25 15:02:40 +03:00
Atanas Korchev
2f243ab266 RadzenPassword uses GetClassList. 2021-09-25 15:00:11 +03:00
Atanas Korchev
7a0fa222c4 RadzenRadioButtonList uses ClassList and GetClassList. 2021-09-25 14:58:22 +03:00
Atanas Korchev
88d036c636 RadzenSelectBar uses ClassList and GetClassList. 2021-09-25 14:42:46 +03:00
Atanas Korchev
3b510a6073 RadzenSwitch uses GetClassList. 2021-09-25 14:33:39 +03:00
Atanas Korchev
5cfd7cd69a RadzenAutoComplete uses ClassList and GetClassList. 2021-09-25 14:19:00 +03:00
Atanas Korchev
d5a5a7fd17 RadzenFileInput uses ClassList and GetClassList. 2021-09-25 14:14:53 +03:00
Atanas Korchev
b9989b36dc RadzenNumeric uses GetClassList. 2021-09-25 14:05:55 +03:00
Atanas Korchev
84f1f4969b RadzenMask uses GetClassList. 2021-09-25 14:02:44 +03:00
Atanas Korchev
1945dbdbc3 RadzenDatePicker uses ClassList. 2021-09-25 14:02:31 +03:00
Atanas Korchev
cc4a905685 RadzenDropDown and RadzenDropDownDataGrid use GetClassList. 2021-09-25 13:54:34 +03:00
Atanas Korchev
7b6630512b Fix RadzenCheckBox class. 2021-09-25 13:49:05 +03:00
Atanas Korchev
63e0f14ad3 RadzenTextBox uses GetClassList.Refactor common FormComponent class states into GetClassList. 2021-09-25 13:15:55 +03:00
Atanas Korchev
18054e9603 RadzenTextBox uses ClassList. 2021-09-25 13:02:12 +03:00
Atanas Korchev
9a6c652da0 RadzenCheckBox uses ClassList. 2021-09-25 12:58:32 +03:00
Atanas Korchev
55423425d7 Introduce ClassList helper. Use the ClassList in RadzenTabItem. Closes #227. 2021-09-25 12:06:13 +03:00
Atanas Korchev
d436094e8c RadzenCheckBox label support. 2021-09-25 11:28:42 +03:00
Vladimir Enchev
9184b038b3 Fixed potential deadlocks in synchronous code
FIxed #225
2021-09-24 10:30:06 +03:00
Vladimir Enchev
aad020b9b9 Popup close on resize and width sync fixed 2021-09-23 16:25:48 +03:00
Vladimir Enchev
64b6bbd45b Radzen.Blazor version updated 2021-09-23 10:12:31 +03:00
Vladimir Enchev
58724320b6 Fixed DropDown closed immediately when you click in the lower right corner 2021-09-23 09:42:13 +03:00
Vladimir Enchev
20fbdc7130 DropDown select all functionality improved 2021-09-22 17:12:05 +03:00
Vladimir Enchev
93aed2580e DataGrid row hover styles fixed with frozen columns 2021-09-22 10:10:59 +03:00
Vladimir Enchev
5e8ceae3da Merge branch 'master' of https://github.com/radzenhq/radzen-blazor 2021-09-21 10:01:51 +03:00
Vladimir Enchev
2f26e555f9 GroupDescriptor Property changed to Employee.LastName 2021-09-21 10:01:42 +03:00
yordanov
48b3555e40 Style components links 2021-09-21 09:58:15 +03:00
Vladimir Enchev
657852a82f Radzen.Blazor version updated 2021-09-21 09:38:17 +03:00
Atanas Korchev
dd812ca58c The chart series Visible property can now beset as a parameter. 2021-09-20 16:18:04 +03:00
Vladimir Enchev
2c37075c22 GroupDescriptor Title added 2021-09-20 16:08:13 +03:00
Vladimir Enchev
c895de54bf DataGrid GroupFooterTemplate and GroupFooterCssClass column properties added 2021-09-20 15:15:57 +03:00
yordanov
3e9c2e0131 Fix layouts in data viz demos 2021-09-20 10:01:49 +03:00
yordanov
075099d217 Fix links to blazor docs 2021-09-16 13:31:05 +03:00
yordanov
91e614d6ea Add resposive styles to Get Started page 2021-09-16 13:31:05 +03:00
yordanov
5167ebd7c4 Fix dashboard container padding 2021-09-16 13:31:05 +03:00
yordanov
b5ecc66ea2 Update console styles 2021-09-16 13:31:05 +03:00
yordanov
f49ef8b999 Update link to component docs 2021-09-16 13:31:05 +03:00
yordanov
6691082bb7 Add next step to Get Started page 2021-09-16 13:31:05 +03:00
yordanov
8956cd45c9 Add Header links 2021-09-16 13:31:05 +03:00
yordanov
33178022ec Rename First Look to Overview 2021-09-16 13:31:05 +03:00
yordanov
e0f034c911 Style Get Started page 2021-09-16 13:31:05 +03:00
yordanov
65183c8142 Style Support page 2021-09-16 13:31:05 +03:00
yordanov
a1dce3c1e3 Style GetStarted page 2021-09-16 13:31:05 +03:00
yordanov
27381582f8 Fix link targets 2021-09-16 13:31:05 +03:00
yordanov
326e27f0cd Update demos layout and footer 2021-09-16 13:31:05 +03:00
yordanov
f2fc6d2299 Reorder examples 2021-09-16 13:31:05 +03:00
yordanov
06af4a926a Add pre and code tag styles 2021-09-16 13:31:05 +03:00
yordanov
672236ba8f Add top-nav and responsive styles 2021-09-16 13:31:05 +03:00
yordanov
2f692a206d Update favicon 2021-09-16 13:31:05 +03:00
yordanov
ac74479c3c Add list of components 2021-09-16 13:31:05 +03:00
Atanas Korchev
88a1a56e9b Add Anchor component. 2021-09-16 13:31:05 +03:00
yordanov
12c4ff669a Add new home layout 2021-09-16 13:31:05 +03:00
Vladimir Enchev
48576c8dfb Version updated 2021-09-16 10:16:40 +03:00
Vladimir Enchev
6802e4a136 Fixed AutoComplete popup will not close on first item select 2021-09-16 10:07:55 +03:00
douglassimaodev
4be4b69d15 Input css class parameter (#214)
* AllowInput Implementation

* Remove empty new line.

* Allow User to set a specific class to the input element

* Revert "Allow User to set a specific class to the input element"

This reverts commit 0f36656939.

* new parameter
    public string InputClass { get; set; }

Co-authored-by: Douglas Simao <douglas.simao@hse.ie>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-09-14 09:53:51 +03:00
Vladimir Enchev
a10855cb4d selectTab() code improved 2021-09-13 11:23:54 +03:00
Vladimir Enchev
01aa69185e SelectTabOnClient code improved 2021-09-10 16:19:44 +03:00
Vladimir Enchev
aa1c50f7a7 Tabs will be switched using JavaScript when TabRenderMode is Client) 2021-09-10 12:11:04 +03:00
Vladimir Enchev
a74e071847 DataGrid and DropDownBase Virtualize exposed 2021-09-09 15:01:52 +03:00
Vladimir Enchev
67a084e597 version updated 2021-09-09 09:16:54 +03:00
Vladimir Enchev
c5b84d1fa0 DataGrid second level and below group items cannot be collapsed 2021-09-08 15:42:38 +03:00
Vladimir Enchev
d8468be21a Steps ShowStepsButtons and StepsCollection properties added. NextStep() and PrevStep() made public 2021-09-07 14:14:29 +03:00
Vladimir Enchev
c31b7598e4 Fixed DatePicker throws exception when using DateTimeOffset and date is manually changed
Fix #211
2021-09-07 10:35:07 +03:00
Vladimir Enchev
fa3dc1add1 global.json added to ignore 2021-09-03 15:44:00 +03:00
Vladimir Enchev
81a405c48c version and Dynamic Linq updated 2021-09-03 15:26:52 +03:00
Vladimir Enchev
0dc54213fc Numeric component will not allow decimal symbol for integer value 2021-09-02 17:11:46 +03:00
Vladimir Enchev
7adeeaf607 Numeric oninput removed to avoid fast type problems 2021-09-01 15:29:23 +03:00
Vladimir Enchev
c316f03b10 Fixed Input will accept invalid value if bound
https://forum.radzen.com/t/datagrid-inline-edit-on-int-sql-server-fields/8837/5
2021-09-01 11:49:59 +03:00
Vladimir Enchev
fa96e6dc3a DataGrid column resizer CSS class added 2021-09-01 10:36:55 +03:00
Vladimir Enchev
bff57c695e DataGrid column header drag will check if column is Groupable 2021-08-31 15:34:44 +03:00
Vladimir Enchev
73ad7a1923 version updated 2021-08-31 11:01:34 +03:00
Vladimir Enchev
4f0c23f6f1 DataGrid should not perform any internal sorting or filtering if bound with LoadData 2021-08-31 10:58:03 +03:00
Vladimir Enchev
e40f9ac769 Radzen.Blazor updated 2021-08-30 10:33:34 +03:00
Vladimir Enchev
11d0fe0191 Version updated 2021-08-30 10:29:05 +03:00
Vladimir Enchev
ca60b9e579 examples source code fixed 2021-08-30 09:51:21 +03:00
Vladimir Enchev
f424ab3a1f DataGrid column drag visual not positioned correctly when document scrolled 2021-08-30 09:32:03 +03:00
Vladimir Enchev
a72357397e Null ref. exception fixed 2021-08-26 13:00:20 +03:00
Vladimir Enchev
819bf7a84e Radzen.Blazor updated 2021-08-25 15:19:18 +03:00
Vladimir Enchev
b2b597542d DataGrid initial column filtering fixed 2021-08-25 15:15:59 +03:00
Vladimir Enchev
c4608f9465 Radzen.Blazor updated 2021-08-25 11:32:58 +03:00
Vladimir Enchev
6828ee95d7 Version updated 2021-08-25 11:24:49 +03:00
Vladimir Enchev
3cecde7c50 DataGrid column null ref. exception fixed when SortOrder is bound to null
Fix #204
2021-08-25 09:54:16 +03:00
Vladimir Enchev
1aec2dbfb4 DataGrid loading panel not working properly with frozen columns 2021-08-25 07:21:03 +03:00
Vladimir Enchev
ba3f28cd5b DataGrid and DataList pager Count not calculated properly 2021-08-24 09:42:03 +03:00
Vladimir Enchev
b8b6a749ce Switch mouse events not raised 2021-08-23 20:32:45 +03:00
Vladimir Enchev
1d1c64119d Radzen.Blazor updated 2021-08-23 18:01:34 +03:00
Vladimir Enchev
e93e4d03a1 Version updated 2021-08-23 17:56:26 +03:00
Vladimir Enchev
1ddbb1b197 Fixed DropDown LINQ expression cannot be translated with AllowFiltering and IQueryable 2021-08-23 07:06:20 +03:00
Vladimir Enchev
3632c3b19e DataGrid InsertRow() fixed to work with LoadData binding 2021-08-20 17:23:09 +03:00
Vladimir Enchev
25651d84dd DataGrid InsertRow() will break the pager if not on first page 2021-08-20 16:58:46 +03:00
Vladimir Enchev
5a59b245ce Focused element lost after DropDown select 2021-08-20 16:28:10 +03:00
Vladimir Enchev
cf33f8bf74 DataGrid group rows not update on groups remove 2021-08-19 18:46:24 +03:00
Atanas Korchev
bfb86a67da DataGrid validation does not work. 2021-08-19 18:23:22 +03:00
douglassimaodev
c076f7641d AllowInput Implementation (#201)
* AllowInput Implementation

Co-authored-by: Douglas Simao <douglas.simao@hse.ie>
2021-08-19 17:06:19 +03:00
Vladimir Enchev
ff6efc7681 Radzen.Blazor updated 2021-08-18 19:14:23 +03:00
Vladimir Enchev
30a0583aab Version updated 2021-08-18 18:33:39 +03:00
Atanas Korchev
ea27a1802d Use oninput to prevent bypassing of the mask. 2021-08-18 18:24:47 +03:00
Vladimir Enchev
9c23bbd309 Radzen.Blazor updated 2021-08-18 12:42:01 +03:00
Vladimir Enchev
a0680ffa8f Version updated 2021-08-18 12:36:46 +03:00
Vladimir Enchev
94c4b723ad DataGrid GroupHeaderText renamed to GroupPanelText 2021-08-18 12:36:08 +03:00
Vladimir Enchev
23ee6c2bb1 Fixed component cannot be focused after leaving DropDown 2021-08-18 10:50:26 +03:00
Vladimir Enchev
02058e523f Radzen.Blazor updated 2021-08-18 09:55:01 +03:00
Vladimir Enchev
e1951f3637 Version updated 2021-08-18 09:51:52 +03:00
Vladimir Enchev
7039478ebc DataGrid grouping support added (#199)
* grouping by column added

* grouping examples added

* group model added

* Groups exposed
2021-08-18 09:50:08 +03:00
Vladimir Enchev
ff566466c8 Fixed reordering DataGrid columns with hidden columns is not working
Fix #194
2021-08-16 09:06:45 +03:00
Vladimir Enchev
3dae1aac2d Fixed DropDownDataGrid exception when filtering non string data
Fix #196
2021-08-16 08:59:32 +03:00
Vladimir Enchev
43dad21cad Radzen.Blazor updated 2021-08-09 11:13:15 +03:00
Vladimir Enchev
9f07373e33 Version updated 2021-08-09 11:07:07 +03:00
Vladimir Enchev
b09e4f3b6a Login tests updated 2021-08-09 11:06:40 +03:00
Vladimir Enchev
be66132498 Count not correct when filtering 2021-08-09 09:28:42 +03:00
viordash
a6a70cc88e Fix pager visibility (#192)
* RadzenPager. disable hiding by count of items if PageSizeOptions are specified

* add tests for Pager
2021-08-09 09:24:00 +03:00
viordash
63d04b7734 RadzenPager. fix current page selection after page size changed (#193) 2021-08-09 09:23:47 +03:00
Vladimir Enchev
90edd71274 DataGrid column reorder (#191)
* DataGrid columns reorder added

* Columns reorder demo updated

* ColumnReordered event added to demo
2021-08-06 18:45:33 +03:00
Vladimir Enchev
db0252dc2c Examples filtering fixed 2021-08-06 10:32:44 +03:00
Vladimir Enchev
8b3e13ecba DataGrid DoesNotContain not working properly with LoadData binding 2021-08-04 09:49:22 +03:00
Vladimir Enchev
5ac96dd852 Tooltip dispose fixed 2021-08-04 09:39:27 +03:00
Vladimir Enchev
cf1ad22af1 Radzen.Blazor updated 2021-08-03 10:53:48 +03:00
Vladimir Enchev
4cf7e6888b Version updated 2021-08-02 15:47:27 +03:00
Vladimir Enchev
1aa4e8bbb2 Fixed item select in DropDown bound to KeyValuePair throws exception 2021-08-02 15:47:04 +03:00
Vladimir Enchev
d9db327ffa Dashboard demo data fixed
Fix #190
2021-08-02 15:03:40 +03:00
GioeEng
6f484766ac Error in icon representation. Incorrect design compromised panel behavior (#188)
* New splitter component

* New Splitter component

* Fixed code style and naming conventions

* themes implemented

* Splitter: Error in icon representation. Incorrect design compromised panel behavior

Co-authored-by: lorenzo <lorenzo.muccioli@car-tech.com>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2021-08-02 10:21:11 +03:00
Vladimir Enchev
9b6468c0b4 Radzen.Blazor updated 2021-07-29 16:05:50 +03:00
Vladimir Enchev
c5880c9096 Version updated 2021-07-29 15:58:05 +03:00
GioeEng
4d588b62cb New splitter component (#166)
* New splitter component

* New Splitter component

* Fixed code style and naming conventions

* themes implemented

Co-authored-by: lorenzo <lorenzo.muccioli@car-tech.com>
Co-authored-by: Vladimir Enchev <vladimir.enchev@gmail.com>
2021-07-29 15:56:38 +03:00
Vladimir Enchev
f6d2ab2e0e Fixed virtualization with LoadData and OData service 2021-07-29 10:15:35 +03:00
Vladimir Enchev
c52636a6e8 DropDownDataGrid initial PageSize not respected 2021-07-28 11:38:39 +03:00
Atanas Korchev
a24fb43ae8 Popup position is inverted when there is enough space for it. 2021-07-27 12:02:05 +03:00
Vladimir Enchev
8f7ead0687 Radzen.Blazor updated 2021-07-26 10:07:45 +03:00
Vladimir Enchev
39e6cc64a2 Version updated 2021-07-26 09:57:32 +03:00
Vladimir Enchev
4f985776e1 DataGrid Single ExpandMode does nothing when RowExpand is not set
Fix #179
2021-07-26 09:03:17 +03:00
Marco Papst
b9e992f118 allow to use RenderFragment for empty DataGrids (#184)
* allow to use RenderFragment for empty DataGrids

* remove cshtml file

* revert sln file from VS2022
2021-07-26 08:45:19 +03:00
Ken Dudley
39e5f969e8 Fixed bug for topandbottom pager at the same time. bottomPager was named topPager (#180)
Co-authored-by: Kenneth Dudley <kenneth.dudley@lumen.com>
2021-07-23 09:25:57 +03:00
Vladimir Enchev
ee79ce4bf6 Radzen.Blazor updated 2021-07-21 16:50:34 +03:00
Vladimir Enchev
20e7a98395 Version updated 2021-07-21 16:47:02 +03:00
Vladimir Enchev
c66be99be7 MenuItem and PanelMenuItem Template added
Fix #177
2021-07-21 16:46:49 +03:00
Vladimir Enchev
0bb5873fc5 Fixed DropDownDataGrid paging controls will close the popup
Fix #178
2021-07-21 09:08:23 +03:00
Vladimir Enchev
50bf0b4a3b DoesNotContainText fixed 2021-07-21 08:45:24 +03:00
Vladimir Enchev
d664652b53 Badge Visible fixed 2021-07-21 07:10:25 +03:00
Vladimir Enchev
77d500235b DataGrid FilterOperator DoesNotContain added 2021-07-20 11:08:32 +03:00
Vladimir Enchev
a7811d9425 Radzen.Blazor updated 2021-07-19 09:57:10 +03:00
Vladimir Enchev
6c6d9d507f Version updated 2021-07-19 09:51:36 +03:00
Vladimir Enchev
36ebc21d3e DataGrid boolean filter should be applied on Apply button 2021-07-19 09:51:17 +03:00
Vladimir Enchev
12f900cb6c Radzen.Blazor updated 2021-07-19 08:48:29 +03:00
Vladimir Enchev
e515bb4933 Version updated 2021-07-19 08:46:02 +03:00
Atanas Korchev
d93f46f4d6 RowDoubleClick does not fire for cells in edit mode. 2021-07-16 08:24:11 +03:00
viordash
1d4aaf04fd Radzen data grid column filter (#172)
* сolumn Type parameter is used as dominant for filterPropertyType

* WIP. add test for DataGridColumn filter property type

* assign filterPropertyType from Type only when FilterProperty is empty, otherwise assign filter type from FilterProperty field && add related tests

* clean code
2021-07-15 07:08:39 +03:00
Vladimir Enchev
65469210b1 Missing documentation links fixed 2021-07-14 19:53:11 +03:00
Marco Papst
88a8bf2769 Feature/badge component (#171)
* fix button unit test

* add RadzenBadge Component

* add RadzenBadge Component tests

* use scss & rz- classes instead of bootstrap

* add missing newline

* add badge scss to components

* remove underlined text from badge link

* cleanup badge page

* remove badge as link

* Add the inherited attributes from RadzenComponent.

Co-authored-by: Marco Papst <papst@sma.de>
Co-authored-by: Atanas Korchev <akorchev@gmail.com>
2021-07-14 16:29:19 +03:00
Vladimir Enchev
8429ff3150 Radzen.Blazor updated 2021-07-13 08:51:14 +03:00
Vladimir Enchev
890d352a65 Version updated 2021-07-13 08:48:25 +03:00
Vladimir Enchev
acb85071f0 Fixed context menu throws exception
Fix #170
2021-07-13 08:32:31 +03:00
Vladimir Enchev
e41a60613c Fixed DataGrid boolean column second filter 2021-07-12 18:55:41 +03:00
Vladimir Enchev
9001668e1b DataGrid null reference exception fixed when accessing columns value fromsub properties 2021-07-12 09:42:00 +03:00
Vladimir Enchev
7b78f22fcc Radzen.Blazor updated 2021-07-08 06:56:10 +03:00
Vladimir Enchev
b614e6c1a4 Version updated 2021-07-08 06:53:58 +03:00
Vladimir Enchev
187abcbcdf Popup close on scroll reworked 2021-07-07 20:16:05 +03:00
Vladimir Enchev
5a3a755f1a Should not close popups on mobile devices scroll
DropDown popup closes when trying to type something for filter
2021-07-07 15:23:25 +03:00
Vladimir Enchev
386e539148 Radzen.Blazor updated 2021-07-05 16:49:59 +03:00
Vladimir Enchev
d05375447b Version updated 2021-07-05 16:46:59 +03:00
Vladimir Enchev
0fc5791b8e DataGrid filtering by numeric not working in simple mode
Fix #165
2021-07-05 16:46:28 +03:00
Vladimir Enchev
0e4f851098 Radzen.Blazor updated 2021-07-05 16:32:43 +03:00
Vladimir Enchev
2488378099 version updated 2021-07-05 16:28:49 +03:00
Vladimir Enchev
b906890de1 Cannot check Tree item when AllowCheckChildren is set to false 2021-07-05 16:28:16 +03:00
762 changed files with 57577 additions and 15774 deletions

8
.gitignore vendored
View File

@@ -8,6 +8,7 @@
*.user
*.userosscache
*.sln.docstates
global.json
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
@@ -333,3 +334,10 @@ issues.json
Radzen.Blazor/wwwroot/css/
project.csproj
RadzenBlazorDemos/wwwroot/docs/
Radzen.DocFX/obj/
Radzen.DocFX/_site/
Radzen.DocFX/_exported_templates
Radzen.DocFX/api/*.yml
!Radzen.DocFX/api/index.md
Radzen.DocFX/api/.manifest

View File

@@ -5,21 +5,19 @@
This is a set of guidelines for contributing to Radzen.Blazor.
## Asking questions
Please don't open an issue to ask a question about using Radzen.Blazor components. You can check the following resources instead:
- [Online demos](https://blazor.radzen.com)
### [Online demos](https://blazor.radzen.com)
A showcase application that demonstrates all Radzen.Blazor components. You will find various use cases that demonstrate the component features and API. The source
of the demos is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/RadzenBlazorDemos).
- [Documentation](https://www.radzen.com/documentation/blazor/accordion/)
### [Documentation](https://blazor.radzen.com/docs/)
Technical documentation and API reference.
- [Online forum](https://forum.radzen.com)
### [Community forum](https://forum.radzen.com)
You can ask your question here. Please use the [Radzen.Blazor Components](https://forum.radzen.com/c/blazor-components/10) category.
- Dedicated technical support
### Dedicated technical support
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/pricing/).
@@ -67,7 +65,8 @@ Explain the enhancement and include additional details:
If you want to contribute a new feature of fix a bug you can open a pull request.
Make sure you follow this procedure:
* **Important!!!** if you itent to make a lot of changes in a pull request open an issue to discuss this with us first. The Radzen Blazor Components have a lot of
moving parts and making big changes should be done with extra precautions.
* **Be sure that none of the existing tests** breaks after your changes. The test project is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/Radzen.Blazor.Tests).
* **If possible add new tests that verify your fix or new feature**.
* **Follow the existing coding style** (to be described in detail later).

30
Dockerfile Normal file
View File

@@ -0,0 +1,30 @@
# syntax=docker/dockerfile:1
FROM mono:latest
ENV DOCFX_VER 2.58.4
RUN apt-get update && apt-get install unzip wget git -y && wget -q -P /tmp https://github.com/dotnet/docfx/releases/download/v${DOCFX_VER}/docfx.zip && \
mkdir -p /opt/docfx && \
unzip /tmp/docfx.zip -d /opt/docfx && \
echo '#!/bin/bash\nmono /opt/docfx/docfx.exe $@' > /usr/bin/docfx && \
chmod +x /usr/bin/docfx && \
rm -rf /tmp/*
COPY Radzen.Blazor /app/Radzen.Blazor
COPY Radzen.DocFX /app/DocFX
COPY RadzenBlazorDemos /app/RadzenBlazorDemos
WORKDIR /app
RUN docfx DocFX/docfx.json
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal
COPY --from=0 /app/RadzenBlazorDemos /app
WORKDIR /app
RUN dotnet publish -c Release -o out
COPY RadzenBlazorDemos/northwind.db /app/out
COPY RadzenBlazorDemos/northwind.sql /app/out
ENV ASPNETCORE_URLS http://*:5000
WORKDIR /app/out
ENTRYPOINT ["dotnet", "RadzenBlazorDemos.dll"]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2021 Radzen Ltd
Copyright (c) 2018-2022 Radzen Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

103
README.md
View File

@@ -1,42 +1,113 @@
# Radzen Blazor Components
![Radzen Blazor Components](RadzenBlazorDemos/wwwroot/images/radzen-blazor-components.png)
The home of the [Radzen Blazor components](https://blazor.radzen.com)
<h1 align="center">
Radzen Blazor Components
</h1>
## Commercial support
<p align="center">
A set of <strong>60+ free and open source</strong> native Blazor UI controls.
</p>
Paid support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
<div align="center">
Our flagship product Radzen provides tons of productivity features for Blazor developers:
[See Online Demos](https://blazor.radzen.com) or [Read the Docs](https://blazor.radzen.com/docs/)
</div>
---
<p align="center">
<a href="https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE">
<img alt="License - MIT" src="https://img.shields.io/github/license/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
</a>
<a href="https://www.nuget.org/packages/Radzen.Blazor">
<img alt="Nuget Downloads" src="https://img.shields.io/nuget/dt/Radzen.Blazor?color=%232694F9&label=nuget%20downloads&logo=nuget&style=for-the-badge" />
</a>
<img alt="Last Commit" src="https://img.shields.io/github/last-commit/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
<a href="https://github.com/radzenhq/radzen-blazor/graphs/contributors">
<img alt="Github Contributors" src="https://img.shields.io/github/contributors/radzenhq/radzen-blazor?logo=github&style=for-the-badge" />
</a>
<a href="https://blazor.radzen.com">
<img alt="Radzen Blazor Components - Online Demos" src="https://img.shields.io/badge/demos-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
</a>
<a href="https://blazor.radzen.com/docs">
<img alt="Radzen Blazor Components - Documentation" src="https://img.shields.io/badge/docs-online-brightgreen?color=%232694F9&logo=blazor&style=for-the-badge" />
</a>
</p>
## Why choose Radzen Blazor Components?
### :sparkles: Free
Radzen Blazor Components are open source and free for commercial use. You can install them from [nuget](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
Paid support is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
### :computer: Native
The components are implemented in C# and take full advantage of the Blazor framework. They do not depend on or wrap existing JavaScript frameworks or libraries.
Blazor Server and Blazor WebAssembly are fully supported.
### :seedling: Growing
We add new components and features on a regular basis.
Short development cycle. We release as soon as new stuff is available. No more quarterly releases.
## Support exceeding your expectations
### :speech_balloon: Community Support
Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.com/). Join the growing community and participate in the discussions!
### :dart: Dedicated Support
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
Our flagship product [Radzen Studio](https://www.radzen.com/features/) provides tons of productivity features for Blazor developers:
- The first in the industry WYSIWYG Blazor design time canvas
- Scaffolding a complete CRUD applications from a database
- Built-in security - authentication and authorization
- Visual Studio Code and Professional support
- Deployment to IIS and Azure
- Dedicated support with 24 hour guaranteed response time
- Active community forum
## Get started with the Radzen Blazor Components
## Get started with Radzen Blazor Components
### Install
### 1. Install
Radzen Blazor Components are distributed as the Radzen.Blazor nuget package. You can add them to your project in one of the following ways
- Install the package from command line by running dotnet add package Radzen.Blazor
Radzen Blazor Components are distributed as a [Radzen.Blazor nuget package](https://www.nuget.org/packages/Radzen.Blazor). You can add them to your project in one of the following ways
- Install the package from command line by running `dotnet add package Radzen.Blazor`
- Add the project from the Visual Nuget Package Manager
- Manually edit the .csproj file and add a project reference
### Import the namespace
### 2. Import the namespace
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
### Include a theme
### 3. Include a theme
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include a theme CSS file by adding this snippet `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">` or `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">` if you either include Bootstrap manually or don't use it at all.
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6+), `Pages\_Host.cshtml` (Blazor Server before .NET 6) or `wwwroot/index.html` (Blazor WebAssembly) and include a theme CSS file by adding this snippet
```html
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">
```
If you either add Bootstrap manually or don't use it at all, include this instead:
```html
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">
```
### Include Radzen.Blazor.js
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include this snippet `<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>`
### 4. Include Radzen.Blazor.js
### Use a component
Open `Pages\_Layout.cshtml` (Blazor Server .NET 6+), `Pages\_Host.cshtml` (Blazor Server before .NET 6) or `wwwroot/index.html` (Blazor WebAssembly) and include this snippet:
```html
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
```
### 5. Use a component
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
```html
<RadzenButton Text="Hi"></RadzenButton>

View File

@@ -0,0 +1,47 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class BadgeTests
{
[Fact]
public void Badge_Renders_TextParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBadge>();
var text = "Test";
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
Assert.Contains(text, component.Markup);
}
[Fact]
public void Badge_Renders_ChildContent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBadge>();
component.SetParametersAndRender(parameters => parameters.AddChildContent("SomeContent"));
Assert.Contains(@$"SomeContent", component.Markup);
}
[Fact]
public void Badge_Renders_BadgeStyle()
{
var badgeStyle = BadgeStyle.Danger;
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBadge>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.BadgeStyle, badgeStyle));
Assert.Contains($"badge-{badgeStyle.ToString().ToLower()}", component.Markup);
}
}
}

View File

@@ -0,0 +1,77 @@
using Bunit;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class BreadCrumbTests
{
[Fact]
public void BreadCrumb_Renders_Items()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBreadCrumb>();
component.SetParametersAndRender(parameters =>
{
parameters.Add(c => c.ChildContent, builder =>
{
builder.OpenComponent<RadzenBreadCrumbItem>(0);
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
builder.CloseComponent();
});
});
//@"<RadzenBreadCrumbItem Text=""Test"" />"
Assert.Contains(@"class=""rz-breadcrumb-item", component.Markup);
Assert.Contains(">Test</", component.Markup);
}
[Fact]
public void BreadCrumb_Renders_Icon()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBreadCrumb>();
component.SetParametersAndRender(parameters =>
{
parameters.Add(c => c.ChildContent, builder =>
{
builder.OpenComponent<RadzenBreadCrumbItem>(0);
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
builder.CloseComponent();
});
});
//@"<RadzenBreadCrumbItem Text=""Test"" />"
Assert.Contains("<i", component.Markup);
Assert.Contains(">add</i>", component.Markup);
}
[Fact]
public void BreadCrumb_Renders_Link()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenBreadCrumb>();
component.SetParametersAndRender(parameters =>
{
parameters.Add(c => c.ChildContent, builder =>
{
builder.OpenComponent<RadzenBreadCrumbItem>(0);
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
builder.AddAttribute(3, nameof(RadzenBreadCrumbItem.Path), "/badge");
builder.CloseComponent();
});
});
//@"<RadzenBreadCrumbItem Text=""Test"" />"
Assert.Contains("<i", component.Markup);
Assert.Contains(">add</i>", component.Markup);
Assert.Contains("<a href=\"/badge", component.Markup);
}
}
}

View File

@@ -51,7 +51,7 @@ namespace Radzen.Blazor.Tests
Assert.DoesNotContain(@$"<i class=""rz-button-icon-left rzi"">{icon}</i>", component.Markup);
// renders the icon with busy spin animation
Assert.Contains(@"<i style=""animation: button-icon-spin", component.Markup);
Assert.Contains(@"<i style=""animation: rotation", component.Markup);
Assert.Contains(">refresh</i>", component.Markup);
}

View File

@@ -110,7 +110,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
component.Find("div").MouseUp();
component.Find("div.rz-chkbox-box").Click();
Assert.True(raised);
}
@@ -126,7 +126,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
component.Find("div").MouseUp();
component.Find("div.rz-chkbox-box").Click();
Assert.True(raised);
}
@@ -141,21 +141,21 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.TriState, true));
component.Find("div").MouseUp();
component.Find("div.rz-chkbox-box").Click();
component.Render();
Assert.Contains(@$"rz-state-active", component.Markup);
Assert.Contains(@$"rzi-check", component.Markup);
component.Find("div").MouseUp();
component.Find("div.rz-chkbox-box").Click();
component.Render();
Assert.DoesNotContain(@$"rz-state-active", component.Markup);
Assert.DoesNotContain(@$"rzi-check", component.Markup);
component.Find("div").MouseUp();
component.Find("div.rz-chkbox-box").Click();
Assert.Contains(@$"rz-state-active", component.Markup);
Assert.Contains(@$"rzi-times", component.Markup);

View File

@@ -2,9 +2,7 @@ using AngleSharp.Dom;
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Radzen.Blazor.Rendering;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
@@ -22,9 +20,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.CloseComponent();
@@ -63,9 +63,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1}, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.CloseComponent();
@@ -86,9 +88,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Title", "MyId");
builder.CloseComponent();
@@ -107,20 +111,23 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
builder.CloseComponent();
});
parameterBuilder.Add<bool>(p => p.AllowSorting, true) ;
parameterBuilder.Add<bool>(p => p.AllowSorting, true);
});
Assert.Contains(@$"rz-sortable-column", component.Markup);
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowSorting, false);
});
@@ -134,9 +141,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
@@ -156,9 +165,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
@@ -169,7 +180,8 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rz-cell-filter", component.Markup);
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowFiltering, false);
});
@@ -183,9 +195,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
@@ -205,9 +219,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, new[] { new { Id = 1 }, new { Id = 2 }, new { Id = 3 } });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
@@ -219,7 +235,8 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rz-grid-filter", component.Markup);
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<FilterMode>(p => p.FilterMode, FilterMode.Simple);
});
@@ -233,9 +250,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
builder.AddAttribute(1, "HeaderTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
@@ -257,9 +276,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 });
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<int>));
builder.AddAttribute(1, "FooterTemplate", (RenderFragment)delegate (RenderTreeBuilder b)
@@ -284,9 +305,11 @@ namespace Radzen.Blazor.Tests
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder => {
var component = ctx.RenderComponent<RadzenGrid<dynamic>>(parameterBuilder =>
{
parameterBuilder.Add<IEnumerable<dynamic>>(p => p.Data, Enumerable.Range(0, 100).Select(i => new { Id = i }));
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder => {
parameterBuilder.Add<RenderFragment>(p => p.Columns, builder =>
{
builder.OpenComponent(0, typeof(RadzenGridColumn<dynamic>));
builder.AddAttribute(1, "Property", "Id");
builder.AddAttribute(2, "Title", "Id");
@@ -328,9 +351,10 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
});
Assert.Contains(@$"rz-paginator", component.Markup);
@@ -346,7 +370,8 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
});
@@ -355,6 +380,57 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"rz-paginator-bottom", component.Markup);
}
[Fact]
public void DataGrid_Renders_DefaultEmptyText()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
component.Render();
Assert.Contains("No records to display.", component.Markup);
}
[Fact]
public void DataGrid_Renders_EmptyText()
{
string emptyText = "Lorem Ipsum";
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.EmptyText, emptyText);
});
Assert.Contains(emptyText, component.Markup);
}
[Fact]
public void DataGrid_Renders_EmptyTemplate()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenGrid<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Array.Empty<int>()));
component.SetParametersAndRender(parameters =>
{
parameters.Add<RenderFragment>(p => p.EmptyTemplate, builder =>
{
builder.OpenElement(0, "p");
builder.AddContent(0, "Lorem Ipsum");
builder.CloseElement();
});
});
Assert.Contains("<p>Lorem Ipsum</p>", component.Markup);
}
[Fact]
public void DataGrid_Raises_LoadDataEventOnNextPageClick()
{
@@ -367,7 +443,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
LoadDataArgs newArgs = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
@@ -391,7 +468,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
LoadDataArgs newArgs = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
@@ -415,7 +493,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
LoadDataArgs newArgs = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
@@ -440,7 +519,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
LoadDataArgs newArgs = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
});
@@ -464,7 +544,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
@@ -485,7 +566,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
@@ -506,13 +588,15 @@ namespace Radzen.Blazor.Tests
var raised = false;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
});
component.Find(".rz-paginator-last").Click();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
@@ -532,13 +616,15 @@ namespace Radzen.Blazor.Tests
var raised = false;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
});
component.Find(".rz-paginator-last").Click();
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
});
@@ -559,7 +645,8 @@ namespace Radzen.Blazor.Tests
var raised = false;
LoadDataArgs newArgs = null;
component.SetParametersAndRender(parameters => {
component.SetParametersAndRender(parameters =>
{
parameters.Add<bool>(p => p.AllowPaging, true);
parameters.Add<int>(p => p.PageSize, 20);
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });

View File

@@ -1,8 +1,8 @@
using Bunit;
using Radzen.Blazor.Rendering;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Xunit;
namespace Radzen.Blazor.Tests
@@ -230,7 +230,7 @@ namespace Radzen.Blazor.Tests
}
[Fact]
public void DatePicker_Raises_ChangeEventOnNextMonth()
public void DatePicker_NotRaises_ChangeEventOnNextMonth()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
@@ -247,12 +247,11 @@ namespace Radzen.Blazor.Tests
component.Find(".rz-datepicker-next-icon").Click();
Assert.True(raised);
Assert.True(((DateTime)newValue) > DateTime.Now);
Assert.False(raised);
}
[Fact]
public void DatePicker_Raises_ValueChangedEventOnNextMonth()
public void DatePicker_NotRaises_ValueChangedEventOnNextMonth()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
@@ -269,12 +268,11 @@ namespace Radzen.Blazor.Tests
component.Find(".rz-datepicker-next-icon").Click();
Assert.True(raised);
Assert.True(((DateTime)newValue) > DateTime.Now);
Assert.False(raised);
}
[Fact]
public void DatePicker_Raises_ChangeEventOnPrevMonth()
public void DatePicker_NotRaises_ChangeEventOnPrevMonth()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
@@ -291,12 +289,11 @@ namespace Radzen.Blazor.Tests
component.Find(".rz-datepicker-prev-icon").Click();
Assert.True(raised);
Assert.True(((DateTime)newValue) < DateTime.Now);
Assert.False(raised);
}
[Fact]
public void DatePicker_Raises_ValueChangedEventOnPrevMonth()
public void DatePicker_NotRaises_ValueChangedEventOnPrevMonth()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
@@ -313,8 +310,200 @@ namespace Radzen.Blazor.Tests
component.Find(".rz-datepicker-prev-icon").Click();
Assert.False(raised);
}
[Fact]
public void DatePicker_Raises_ValueChangedEvent_Returns_PreviousDateOnInputOnDisabledDates()
{
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
DateTime previousDay = DateTime.Today.AddDays(-1);
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
});
var inputElement = component.Find(".rz-inputtext");
// initialize DateTimeValue
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
inputElement.Change(previousDay.AddDays(-1));
// try to enter disabled date
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
inputElement.Change(DateTime.Today);
Assert.True(raised);
Assert.True(((DateTime)newValue) < DateTime.Now);
Assert.Equal(previousDay, (DateTime)newValue);
}
[Fact]
public void DatePicker_Clears_InputOnDisabledDates()
{
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
DateTime previousDay = DateTime.Today.AddDays(-1);
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters => {
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
});
var inputElement = component.Find(".rz-inputtext");
// initialize DateTimeValue
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
inputElement.Change(previousDay.AddDays(-1));
// try to enter disabled date
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
inputElement.Change(DateTime.Today);
Assert.True(raised);
Assert.Null(newValue);
}
[Fact]
public void DatePicker_Respects_DateTimeMaxValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
{
parameters.Add(p => p.Value, DateTime.MaxValue);
});
Assert.Contains(DateTime.MaxValue.ToString(component.Instance.DateFormat), component.Markup);
var exception = Record.Exception(() => component.Find(".rz-datepicker-next-icon")
.Click());
Assert.Null(exception);
}
[Fact]
public void DatePicker_Respects_DateTimeMinValue()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
{
parameters.Add(p => p.Value, DateTime.MinValue);
});
Assert.Contains(DateTime.MinValue.ToString(component.Instance.DateFormat), component.Markup);
var exception = Record.Exception(() => component.Find(".rz-datepicker-prev-icon")
.Click());
Assert.Null(exception);
}
[Theory]
[InlineData(DateTimeKind.Local)]
[InlineData(DateTimeKind.Unspecified)]
[InlineData(DateTimeKind.Utc)]
public void DatePicker_Respects_DateTimeKind(DateTimeKind kind)
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
{
parameters.Add(x => x.Kind, kind);
parameters.Add(x => x.ShowTime, true);
});
var raised = false;
object newValue = null;
component.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
});
component.Find(".rz-datepicker-next-icon").Click();
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
Assert.True(raised);
Assert.Equal(kind, ((DateTime)newValue).Kind);
}
[Fact]
public void DatePicker_Renders_FooterTemplate()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
string actionsTemplate = "<input type=\"button\" value=\"Test\" />";
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
{
parameters.Add(p => p.Value, DateTime.MinValue);
parameters.Add(p => p.FooterTemplate, actionsTemplate);
});
Assert.Contains(actionsTemplate, component.Markup);
}
[Fact]
public void DatePicker_Converts_DateTimeOffSet_FromUtc_ToLocal()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var valueUtc = DateTimeOffset.UtcNow;
var kind = DateTimeKind.Local;
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
{
parameters.Add(p => p.Kind, kind);
parameters.Add(p => p.Value, valueUtc);
});
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
Assert.Equal(valueUtc.LocalDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
}
[Fact]
public void DatePicker_Converts_DateTimeOffSet_Local_ToUtc()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var valueUtc = DateTimeOffset.Now;
var kind = DateTimeKind.Utc;
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
{
parameters.Add(p => p.Kind, kind);
parameters.Add(p => p.Value, valueUtc);
});
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
Assert.Equal(valueUtc.UtcDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
}
}
}

View File

@@ -45,5 +45,29 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"autofocus", component.Markup);
}
[Fact]
public void Icon_Renders_IconStyleClass()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, IconStyle.Primary));
Assert.Contains(@$"rzi-primary", component.Markup);
}
[Fact]
public void Icon_NotRenders_IconStyleClass_WhenNull()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenIcon>();
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, null));
Assert.DoesNotContain(@$"rzi-primary", component.Markup);
}
}
}

View File

@@ -36,7 +36,7 @@ namespace Radzen.Blazor.Tests
var component = ctx.RenderComponent<RadzenLogin>();
Assert.Contains(@$"<input name=""userName"" class=""rz-textbox""", component.Markup);
Assert.Contains(@$"<input name=""Username""", component.Markup);
}
[Fact]
@@ -89,30 +89,6 @@ namespace Radzen.Blazor.Tests
Assert.True(!clicked);
}
[Fact]
public void Login_Validates_UsernameParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenLogin>();
component.Find("button").Click();
Assert.Contains(@$"Username is required", component.Markup);
}
[Fact]
public void Login_Validates_PasswordParameter()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenLogin>();
component.Find("button").Click();
Assert.Contains(@$"Password is required", component.Markup);
}
[Fact]
public void Login_Renders_LoginTextParameter()
{
@@ -214,7 +190,7 @@ namespace Radzen.Blazor.Tests
parameters.Add(p => p.Register, args => { clicked = true; });
});
component.Find(".btn-secondary").Click();
component.Find(".register > button").Click();
Assert.True(clicked);
}
@@ -240,7 +216,7 @@ namespace Radzen.Blazor.Tests
}
[Fact]
public void Login_NotRaises_ResetPasswordEvent_WhenEmptyUsername()
public void Login_Raises_ResetPasswordEvent_WhenEmptyUsername()
{
using var ctx = new TestContext();
@@ -255,19 +231,7 @@ namespace Radzen.Blazor.Tests
component.Find("a").Click();
Assert.True(!clicked);
}
[Fact]
public void Login_Validates_UsernameParameter_OnResetPasswordEvent()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenLogin>();
component.Find("a").Click();
Assert.Contains(@$"Username is required", component.Markup);
Assert.True(clicked);
}
}
}

View File

@@ -48,6 +48,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters =>
{
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
parameters.Add<double>(p => p.Value, minValue);
parameters.Add<decimal?>(p => p.Min, minValue);
});

View File

@@ -0,0 +1,80 @@
using Bunit;
using Bunit.JSInterop;
using System;
using System.Collections.Generic;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class PagerTests
{
[Fact]
public void RadzenPager_AutoHide_If_Count_Is_Less_Than_PageSize()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPager>(parameters =>
{
parameters.Add<int>(p => p.PageSize, 20);
parameters.Add<int>(p => p.Count, 100);
});
component.Render();
Assert.Contains(@$"rz-paginator", component.Markup);
component.SetParametersAndRender(parameters =>
{
parameters.Add<int>(p => p.PageSize, 101);
parameters.Add<int>(p => p.Count, 100);
});
Assert.DoesNotContain(@$"rz-paginator", component.Markup);
}
[Fact]
public void RadzenPager_Dont_AutoHide_If_PageSizeOptions_Specified()
{
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPager>(parameters =>
{
parameters.Add<int>(p => p.PageSize, 101);
parameters.Add<int>(p => p.Count, 100);
parameters.Add<IEnumerable<int>>(p => p.PageSizeOptions, new int[] { 3, 7, 15 });
});
component.Render();
Assert.Contains(@$"rz-paginator", component.Markup);
Assert.Contains(@$"rz-dropdown-trigger", component.Markup);
}
[Fact]
public async void RadzenPager_Renders_Summary() {
using var ctx = new TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
var component = ctx.RenderComponent<RadzenPager>(parameters => {
parameters.Add<int>(p => p.PageSize, 10);
parameters.Add<int>(p => p.Count, 100);
parameters.Add<bool>(p => p.ShowPagingSummary, true);
});
await component.Instance.GoToPage(2);
component.Render();
Assert.Contains(@$"rz-paginator-summary", component.Markup);
Assert.Contains(@$"Page 3 of 10 (100 items)", component.Markup);
component.SetParametersAndRender(parameters => {
parameters.Add<bool>(p => p.ShowPagingSummary, false);
});
Assert.DoesNotContain(@$"rz-paginator-summary", component.Markup);
}
}
}

View File

@@ -0,0 +1,98 @@
using Bunit;
using Bunit.TestDoubles;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit;
namespace Radzen.Blazor.Tests
{
public class PanelMenuTests
{
class TestNavigationManager : NavigationManager
{
public TestNavigationManager(string uri)
{
Initialize("http://www.example.com/", uri);
}
protected override void NavigateToCore(string uri, bool forceLoad)
{
}
}
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, params string[] urls)
{
using var ctx = new TestContext();
ctx.Services.RemoveAll<NavigationManager>();
ctx.Services.TryAddSingleton<NavigationManager>(new TestNavigationManager(currentAbsoluteUrl));
var component = ctx.RenderComponent<RadzenPanelMenu>();
component.SetParametersAndRender(parameters => parameters.Add(p => p.Match, match).AddChildContent(builder =>
{
foreach (var url in urls)
{
builder.OpenComponent<RadzenPanelMenuItem>(0);
builder.AddAttribute(1, nameof(RadzenPanelMenuItem.Path), url);
builder.CloseComponent();
}
}));
return component.Markup;
}
[Fact]
public void RadzenPanelMenu_SetsOneActiveMenuItem()
{
var component = CreatePanelMenu("http://www.example.com/datagrid-dynamic", NavLinkMatch.All, "/datagrid", "/datagrid-dynamic");
var firstIndex = component.IndexOf("rz-navigation-item-wrapper-active");
var lastIndex = component.LastIndexOf("rz-navigation-item-wrapper-active");
Assert.NotEqual(-1, firstIndex);
Assert.Equal(firstIndex, lastIndex);
}
[Fact]
public void RadzenPanelMenu_MatchesQueryStringParameters()
{
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.Prefix, "/foo");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_DoesNotMatchQueryStringParametersWhenExactMatchIsSpecified()
{
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.All, "/foo");
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_DoesNotMatchRootWithEverything()
{
var component = CreatePanelMenu("http://www.example.com/foo", NavLinkMatch.Prefix, "/");
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_MatchesRoot()
{
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.Prefix, "/");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
[Fact]
public void RadzenPanelMenu_MatchesRootWithoutTrailingSlash()
{
var component = CreatePanelMenu("http://www.example.com", NavLinkMatch.Prefix, "/");
Assert.Contains("rz-navigation-item-wrapper-active", component);
}
}
}

View File

@@ -118,5 +118,27 @@ namespace Radzen.Blazor.Tests
Assert.Contains(@$"style=""width: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
}
[Fact]
public void ProgressBar_Renders_ProgressBarStyle()
{
using var ctx = new TestContext();
var component = ctx.RenderComponent<RadzenProgressBar>();
component.SetParametersAndRender(parameters=>parameters.Add(p=>p.ProgressBarStyle, ProgressBarStyle.Success));
Assert.Contains(@$"rz-progressbar-determinate-success", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
Assert.Contains(@$"rz-progressbar-determinate-info", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Success));
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
Assert.Contains(@$"rz-progressbar-indeterminate-success", component.Markup);
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
Assert.Contains(@$"rz-progressbar-indeterminate-info", component.Markup);
}
}
}

View File

@@ -1,15 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="bunit.web" Version="1.0.0-preview-01" />
<PackageReference Include="bunit.xunit" Version="1.0.0-preview-01" />
<PackageReference Include="bunit.web" Version="1.2.49" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -38,8 +38,8 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.Value, value));
Assert.Contains(@$"style=""width: {(value / max * 100).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""left: {(value / max * 100).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""width: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
Assert.Contains(@$"style=""left: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
}
[Fact]
@@ -55,9 +55,9 @@ namespace Radzen.Blazor.Tests
parameters.Add<IEnumerable<int>>(p => p.Value, new int[] { 4, 30 });
});
Assert.Contains(@$"left: 4.00%", component.Markup);
Assert.Contains(@$"left: 30.0%", component.Markup);
Assert.Contains(@$"left: 4.00%; width: 26.00%;", component.Markup);
Assert.Contains(@$"left: 4%", component.Markup);
Assert.Contains(@$"left: 30%", component.Markup);
Assert.Contains(@$"left: 4%; width: 26%;", component.Markup);
}
[Fact]

View File

@@ -110,7 +110,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
component.Find("div").MouseUp();
component.Find("div").Click();
Assert.True(raised);
Assert.True(object.Equals(value, !(bool)newValue));
@@ -129,7 +129,7 @@ namespace Radzen.Blazor.Tests
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
component.Find("div").MouseUp();
component.Find("div").Click();
Assert.True(raised);
Assert.True(object.Equals(value, !(bool)newValue));

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"excubo.webcompiler": {
"version": "2.6.0",
"commands": [
"webcompiler"
]
}
}
}

View File

@@ -3,13 +3,37 @@ using System.Collections.Generic;
namespace Radzen.Blazor
{
/// <summary>
/// Represents an appointment in <see cref="RadzenScheduler{TItem}" />
/// </summary>
public class AppointmentData
{
/// <summary>
/// Gets or sets the start of the appointment.
/// </summary>
/// <value>The start.</value>
public DateTime Start { get; set; }
/// <summary>
/// Gets or sets the end of the appointment.
/// </summary>
/// <value>The end.</value>
public DateTime End { get; set; }
/// <summary>
/// Gets or sets the text of the appointment.
/// </summary>
/// <value>The text.</value>
public string Text { get; set; }
/// <summary>
/// Gets or sets the data associated with the appointment
/// </summary>
/// <value>The data.</value>
public object Data { get; set; }
/// <summary>
/// Determines whether the specified object is equal to this instance. Used to check if two appointments are equal.
/// </summary>
/// <param name="obj">The object to compare with this instance.</param>
/// <returns><c>true</c> if the specified is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
return obj is AppointmentData data &&
@@ -19,6 +43,10 @@ namespace Radzen.Blazor
EqualityComparer<object>.Default.Equals(Data, data.Data);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode()
{
return HashCode.Combine(Start, End, Text, Data);

View File

@@ -3,45 +3,106 @@ using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Base class for an axis in <see cref="RadzenChart" />.
/// </summary>
public abstract class AxisBase : RadzenChartComponentBase, IChartAxis
{
/// <summary>
/// Gets or sets the stroke (line color) of the axis.
/// </summary>
/// <value>The stroke.</value>
[Parameter]
public string Stroke { get; set; }
/// <summary>
/// Gets or sets the pixel width of axis.
/// </summary>
/// <value>The width of the stroke.</value>
[Parameter]
public double StrokeWidth { get; set; } = 1;
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the format string used to display the axis values.
/// </summary>
/// <value>The format string.</value>
[Parameter]
public string FormatString { get; set; }
/// <summary>
/// Gets or sets a formatter function that formats the axis values.
/// </summary>
/// <value>The formatter.</value>
[Parameter]
public Func<object, string> Formatter { get; set; }
/// <summary>
/// Gets or sets the type of the line used to display the axis.
/// </summary>
/// <value>The type of the line.</value>
[Parameter]
public LineType LineType { get; set; }
/// <summary>
/// Gets or sets the grid lines configuration of the current axis.
/// </summary>
/// <value>The grid lines.</value>
public RadzenGridLines GridLines { get; set; } = new RadzenGridLines();
/// <summary>
/// Gets or sets the title configuration.
/// </summary>
/// <value>The title.</value>
public RadzenAxisTitle Title { get; set; } = new RadzenAxisTitle();
/// <summary>
/// Gets or sets the ticks configuration.
/// </summary>
/// <value>The ticks.</value>
public RadzenTicks Ticks { get; set; } = new RadzenTicks();
internal int TickDistance { get; set; } = 100;
/// <summary>
/// Gets or sets the pixel distance between axis ticks. It is used to calculate the number of visible ticks depending on the available space. Set to 100 by default;
/// Setting <see cref="Step" /> will override this value.
/// </summary>
/// <value>The desired pixel distance between ticks.</value>
[Parameter]
public int TickDistance { get; set; } = 100;
/// <summary>
/// Specifies the minimum value of the axis.
/// </summary>
/// <value>The minimum.</value>
[Parameter]
public object Min { get; set; }
/// <summary>
/// Specifies the maximum value of the axis.
/// </summary>
/// <value>The maximum.</value>
[Parameter]
public object Max { get; set; }
/// <summary>
/// Specifies the step of the axis.
/// </summary>
[Parameter]
public object Step { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="AxisBase"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
[Parameter]
public bool Visible { get; set; } = true;
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Min), Min) ||

View File

@@ -5,12 +5,22 @@ using System.Linq;
using System.Linq.Dynamic.Core;
using Radzen.Blazor.Rendering;
using System.Threading.Tasks;
using System.Collections;
using Microsoft.AspNetCore.Components.Rendering;
namespace Radzen.Blazor
{
/// <summary>
/// Base class of <see cref="RadzenChart" /> series.
/// </summary>
/// <typeparam name="TItem">The type of the series data.</typeparam>
public abstract class CartesianSeries<TItem> : RadzenChartComponentBase, IChartSeries, IDisposable
{
protected Func<TItem, double> Category(ScaleBase scale)
/// <summary>
/// Creates a getter function that returns a value from the specified category scale for the specified data item.
/// </summary>
/// <param name="scale">The scale.</param>
internal Func<TItem, double> Category(ScaleBase scale)
{
if (IsNumeric(CategoryProperty))
{
@@ -34,16 +44,28 @@ namespace Radzen.Blazor
return (item) => Items.IndexOf(item);
}
/// <summary>
/// Helper function. Used internally.
/// </summary>
protected Func<TItem, double> ComposeCategory(ScaleBase scale)
{
return scale.Compose(Category(scale));
}
/// <summary>
/// Helper function. Used internally.
/// </summary>
protected Func<TItem, double> ComposeValue(ScaleBase scale)
{
return scale.Compose(Value);
}
/// <summary>
/// Determines whether the property with the specified name is <see cref="DateTime" />
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns><c>true</c> if the specified property name is date; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
protected bool IsDate(string propertyName)
{
if (String.IsNullOrEmpty(propertyName))
@@ -61,6 +83,12 @@ namespace Radzen.Blazor
return PropertyAccess.IsDate(property);
}
/// <summary>
/// Determines whether the property with the specified name is numeric.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns><c>true</c> if the specified property name is numeric; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
protected bool IsNumeric(string propertyName)
{
if (String.IsNullOrEmpty(propertyName))
@@ -78,46 +106,118 @@ namespace Radzen.Blazor
return PropertyAccess.IsNumeric(property);
}
/// <inheritdoc />
[Parameter]
public string Title { get; set; }
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the tooltip template.
/// </summary>
/// <value>The tooltip template.</value>
[Parameter]
public RenderFragment<TItem> TooltipTemplate { get; set; }
/// <summary>
/// Gets the list of overlays.
/// </summary>
/// <value>The Overlays list.</value>
public IList<IChartSeriesOverlay> Overlays { get; } = new List<IChartSeriesOverlay>();
/// <summary>
/// Gets the coordinate system of the series.
/// </summary>
/// <value>Coordinate system enum value.</value>
public virtual CoordinateSystem CoordinateSystem => CoordinateSystem.Cartesian;
/// <summary>
/// The name of the property of <typeparamref name="TItem" /> that provides the X axis (a.k.a. category axis) values.
/// </summary>
[Parameter]
public string CategoryProperty { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="CartesianSeries{TItem}"/> is visible.
/// Invisible series do not appear in the legend and cannot be shown by the user.
/// Use the <c>Visible</c> property to programatically show or hide a series.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
[Parameter]
public bool Visible { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="CartesianSeries{TItem}"/> is hidden.
/// Hidden series are initially invisible and the user can show them by clicking on their label in the legend.
/// Use the <c>Hidden</c> property to hide certain series from your users but still allow them to see them.
/// </summary>
/// <value><c>true</c> if hidden; otherwise, <c>false</c>.</value>
[Parameter]
public bool Hidden { get; set; }
bool IsVisible { get; set; } = true;
bool IChartSeries.Visible
{
get
{
return IsVisible;
}
}
/// <inheritdoc />
public bool ShowInLegend { get => Visible; }
/// <summary>
/// The name of the property of <typeparamref name="TItem" /> that provides the Y axis (a.k.a. value axis) values.
/// </summary>
[Parameter]
public string ValueProperty { get; set; }
/// <inheritdoc />
[Parameter]
public int RenderingOrder { get; set; }
protected Func<TItem, double> Value
/// <summary>
/// Creates a getter function that returns a value from the specified data item. Uses <see cref="ValueProperty" />.
/// </summary>
/// <value>The value.</value>
/// <exception cref="ArgumentException">ValueProperty should not be empty</exception>
internal Func<TItem, double> Value
{
get
{
if (String.IsNullOrEmpty(ValueProperty))
{
throw new ArgumentException("ValueProperty shoud not be empty");
throw new ArgumentException("ValueProperty should not be empty");
}
return PropertyAccess.Getter<TItem, double>(ValueProperty);
}
}
/// <summary>
/// Gets or sets the data of the series. The data is enumerated and its items are displayed by the series.
/// </summary>
/// <value>The data.</value>
[Parameter]
public IEnumerable<TItem> Data { get; set; }
/// <summary>
/// Stores <see cref="Data" /> as an IList of <typeparamref name="TItem"/>.
/// </summary>
/// <value>The items.</value>
protected IList<TItem> Items { get; set; } = new List<TItem>();
/// <inheritdoc />
public RadzenMarkers Markers { get; set; } = new RadzenMarkers();
/// <inheritdoc />
public virtual MarkerType MarkerType
{
get
@@ -142,6 +242,17 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Returns the category values
/// </summary>
protected virtual IList<object> GetCategories()
{
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
return Items.Select(category).ToList();
}
/// <inheritdoc />
public virtual ScaleBase TransformCategoryScale(ScaleBase scale)
{
if (Items == null)
@@ -168,9 +279,7 @@ namespace Radzen.Blazor
};
}
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
var data = Items.Select(category).ToList();
var data = GetCategories();
if (scale is OrdinalScale ordinal)
{
@@ -199,6 +308,7 @@ namespace Radzen.Blazor
};
}
/// <inheritdoc />
public virtual ScaleBase TransformValueScale(ScaleBase scale)
{
if (Items != null)
@@ -212,18 +322,55 @@ namespace Radzen.Blazor
return scale;
}
/// <inheritdoc />
public abstract RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
/// <inheritdoc />
public RenderFragment RenderOverlays(ScaleBase categoryScale, ScaleBase valueScale)
{
return new RenderFragment(builder =>
{
builder.OpenRegion(0);
foreach (var overlay in Overlays)
{
if (overlay.Visible)
{
builder.AddContent(1, overlay.Render(categoryScale, valueScale));
}
}
builder.CloseRegion();
});
}
/// <inheritdoc />
public abstract string Color { get; }
double MinValue { get; set; }
double MaxValue { get; set; }
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
var shouldRefresh = parameters.DidParameterChange(nameof(Data), Data);
var visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
var hiddenChanged = parameters.DidParameterChange(nameof(Hidden), Hidden);
await base.SetParametersAsync(parameters);
if (hiddenChanged)
{
IsVisible = !Hidden;
shouldRefresh = true;
}
if (visibleChanged)
{
IsVisible = Visible;
shouldRefresh = true;
}
if (Data != null && Data.Count() != Items.Count)
{
shouldRefresh = true;
}
if (shouldRefresh)
{
if (Data != null)
@@ -241,34 +388,36 @@ namespace Radzen.Blazor
{
Items = Items.AsQueryable().OrderBy(CategoryProperty).ToList();
}
if (Items.Any())
{
MinValue = Items.Min(Value);
MaxValue = Items.Max(Value);
}
}
Chart.Refresh(false);
Chart.DisplayTooltip();
await Chart.Refresh(false);
}
}
/// <inheritdoc />
protected override void Initialize()
{
Chart.AddSeries(this);
}
public virtual bool Contains(double x, double y)
/// <inheritdoc />
public virtual bool Contains(double x, double y, double tolerance)
{
return false;
}
/// <inheritdoc />
public virtual double MeasureLegend()
{
return TextMeasurer.TextWidth(GetTitle());
}
/// <summary>
/// Determines if the provided point is inside the provided polygon.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="polygon">The polygon.</param>
/// <returns><c>true</c> if the polygon contains the point, <c>false</c> otherwise.</returns>
protected bool InsidePolygon(Point point, Point[] polygon)
{
var minX = polygon[0].X;
@@ -304,6 +453,7 @@ namespace Radzen.Blazor
return inside;
}
/// <inheritdoc />
public virtual RenderFragment RenderTooltip(object data, double marginLeft, double marginTop)
{
var item = (TItem)data;
@@ -317,10 +467,7 @@ namespace Radzen.Blazor
builder.AddAttribute(1, nameof(ChartTooltip.X), x + marginLeft);
builder.AddAttribute(2, nameof(ChartTooltip.Y), y + marginTop);
if (TooltipTemplate != null)
{
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate(item));
}
builder.AddAttribute(3, nameof(ChartTooltip.ChildContent), TooltipTemplate == null ? null : TooltipTemplate(item));
builder.AddAttribute(4, nameof(ChartTooltip.Title), TooltipTitle(item));
builder.AddAttribute(5, nameof(ChartTooltip.Label), TooltipLabel(item));
@@ -331,21 +478,30 @@ namespace Radzen.Blazor
};
}
/// <summary>
/// Gets the tooltip inline style.
/// </summary>
/// <param name="item">The item.</param>
protected virtual string TooltipStyle(TItem item)
{
return Chart.Tooltip.Style;
}
/// <summary>
/// Gets the tooltip CSS class.
/// </summary>
/// <param name="item">The item.</param>
protected virtual string TooltipClass(TItem item)
{
return $"rz-series-{Chart.Series.IndexOf(this)}-tooltip";
}
/// <inheritdoc />
public virtual RenderFragment RenderLegendItem()
{
var style = new List<string>();
if (Visible == false)
if (IsVisible == false)
{
style.Add("text-decoration: line-through");
}
@@ -364,6 +520,7 @@ namespace Radzen.Blazor
};
}
/// <inheritdoc />
public double MarkerSize
{
get
@@ -379,59 +536,177 @@ namespace Radzen.Blazor
}
}
private void OnLegendItemClick()
/// <inheritdoc />
public double GetMedian()
{
Chart.ToggleSeries(this);
return Data.Select(e => Value(e)).OrderBy(e => e).Skip(Data.Count() / 2).FirstOrDefault();
}
/// <inheritdoc />
public double GetMean()
{
return Data.Select(e => Value(e)).Average();
}
/// <inheritdoc />
public double GetMode()
{
return Data.GroupBy(e => Value(e)).Select(g => new { Value = g.Key, Count = g.Count() }).OrderByDescending(e => e.Count).FirstOrDefault().Value;
}
/// <summary>
/// https://en.wikipedia.org/wiki/Simple_linear_regression#Fitting_the_regression_line
/// </summary>
public (double a, double b) GetTrend()
{
double a, b;
Func<TItem, double> X;
Func<TItem, double> Y;
if (Chart.ShouldInvertAxes())
{
X = e => Chart.CategoryScale.Scale(Value(e));
Y = e => Chart.ValueScale.Scale(Category(Chart.ValueScale)(e));
}
else
{
X = e => Chart.CategoryScale.Scale(Category(Chart.CategoryScale)(e));
Y = e => Chart.ValueScale.Scale(Value(e));
}
var avgX = Data.Select(e => X(e)).Average();
var avgY = Data.Select(e => Y(e)).Average();
var sumXY = Data.Sum(e => (X(e) - avgX) * (Y(e) - avgY));
if (Chart.ShouldInvertAxes())
{
var sumYSq = Data.Sum(e => (Y(e) - avgY) * (Y(e) - avgY));
b = sumXY / sumYSq;
a = avgX - b * avgY;
}
else
{
var sumXSq = Data.Sum(e => (X(e) - avgX) * (X(e) - avgX));
b = sumXY / sumXSq;
a = avgY - b * avgX;
}
return (a, b);
}
private async Task OnLegendItemClick()
{
IsVisible = !IsVisible;
if (Chart.LegendClick.HasDelegate)
{
var args = new LegendClickEventArgs
{
Data = this.Data,
Title = GetTitle(),
IsVisible = IsVisible,
};
await Chart.LegendClick.InvokeAsync(args);
IsVisible = args.IsVisible;
}
await Chart.Refresh();
}
/// <inheritdoc />
public string GetTitle()
{
return String.IsNullOrEmpty(Title) ? $"Series {Chart.Series.IndexOf(this) + 1}" : Title;
}
/// <summary>
/// Gets the label of the tooltip displayed for this item.
/// </summary>
/// <param name="item">The item.</param>
protected virtual string TooltipLabel(TItem item)
{
return GetTitle();
}
/// <summary>
/// Gets the title of the tooltip displayed for this item.
/// </summary>
/// <param name="item">The item.</param>
protected virtual string TooltipTitle(TItem item)
{
var category = Category(Chart.CategoryScale);
return Chart.CategoryAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(category(item)));
}
/// <summary>
/// Gets the value of the tooltip displayed for this item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
protected virtual string TooltipValue(TItem item)
{
return Chart.ValueAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(Value(item)));
}
protected virtual double TooltipX(TItem item)
/// <summary>
/// Gets the X coordinate of the tooltip of the specified item.
/// </summary>
/// <param name="item">The item.</param>
internal virtual double TooltipX(TItem item)
{
var category = Category(Chart.CategoryScale);
return Chart.CategoryScale.Scale(category(item), true);
}
protected virtual double TooltipY(TItem item)
/// <summary>
/// Gets the Y coordinate of the tooltip of the specified item.
/// </summary>
/// <param name="item">The item.</param>
internal virtual double TooltipY(TItem item)
{
return Chart.ValueScale.Scale(Value(item), true);
}
/// <inheritdoc />
public virtual object DataAt(double x, double y)
{
var first = Items.FirstOrDefault();
var last = Items.LastOrDefault();
if (Items.Any())
{
return Items.Select(item =>
{
var distance = Math.Abs(TooltipX(item) - x);
return new { Item = item, Distance = distance };
}).Aggregate((a, b) => a.Distance < b.Distance ? a : b).Item;
}
var category = Category(Chart.CategoryScale);
var startX = Chart.CategoryScale.Scale(category(first), true);
var endX = Chart.CategoryScale.Scale(category(last), true);
var count = Math.Max(Items.Count() - 1, 1);
var index = Convert.ToInt32((x - startX) / ((endX - startX) / count));
return Items.ElementAtOrDefault(index);
return null;
}
/// <inheritdoc />
public virtual IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
{
var list = new List<ChartDataLabel>();
foreach (var d in Data)
{
list.Add(new ChartDataLabel
{
Position = new Point { X = TooltipX(d) + offsetX, Y = TooltipY(d) + offsetY },
TextAnchor = "middle",
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(d))
});
}
return list;
}
/// <summary>
/// Returns a color from the specified list of colors. Rotates colors.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="colors">The colors.</param>
/// <param name="defaultValue">The default value.</param>
protected string PickColor(int index, IEnumerable<string> colors, string defaultValue = null)
{
if (colors == null || !colors.Any())
@@ -442,9 +717,29 @@ namespace Radzen.Blazor
return colors.ElementAt(index % colors.Count());
}
/// <inheritdoc />
public void Dispose()
{
Chart?.RemoveSeries(this);
}
/// <inheritdoc />
public async Task InvokeClick(EventCallback<SeriesClickEventArgs> handler, object data)
{
var category = Category(Chart.CategoryScale);
await handler.InvokeAsync(new SeriesClickEventArgs
{
Data = data,
Title = GetTitle(),
Category = PropertyAccess.GetValue(data, CategoryProperty),
Value = PropertyAccess.GetValue(data, ValueProperty),
Point = new SeriesPoint
{
Category = category((TItem)data),
Value = Value((TItem)data)
}
});
}
}
}

View File

@@ -1,10 +1,25 @@
namespace Radzen.Blazor
{
/// <summary>
/// Specifies the <see cref="RadzenChart" /> color schemes used when rendering the series.
/// </summary>
public enum ColorScheme
{
/// <summary>
/// Pastel color scheme.
/// </summary>
Pastel,
/// <summary>
/// Palette color scheme.
/// </summary>
Palette,
/// <summary>
/// Divergent color scheme.
/// </summary>
Divergent,
/// <summary>
/// Monochrome color scheme
/// </summary>
Monochrome
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,10 +7,48 @@ using System.Threading.Tasks;
namespace Radzen
{
/// <summary>
/// Class ContextMenuService. Contains various methods with options to open and close context menus.
/// Should be added as scoped service in the application services and RadzenContextMenu should be added in application main layout.
/// Implements the <see cref="IDisposable" />
/// </summary>
/// <seealso cref="IDisposable" />
/// <example>
/// <code>
/// @inject ContextMenuService ContextMenuService
/// &lt;RadzenButton Text="Show context menu" ContextMenu=@(args => ShowContextMenuWithContent(args)) /&gt;
/// @code {
/// void ShowContextMenuWithContent(MouseEventArgs args) =&gt; ContextMenuService.Open(args, ds =&gt;
/// @&lt;RadzenMenu Click="OnMenuItemClick"&gt;
/// &lt;RadzenMenuItem Text="Item1" Value="1"&gt;&lt;/RadzenMenuItem&gt;
/// &lt;RadzenMenuItem Text="Item2" Value="2"&gt;&lt;/RadzenMenuItem&gt;
/// &lt;RadzenMenuItem Text="More items" Value="3"&gt;
/// &lt;RadzenMenuItem Text="More sub items" Value="4"&gt;
/// &lt;RadzenMenuItem Text="Item1" Value="5"&gt;&lt;/RadzenMenuItem&gt;
/// &lt;RadzenMenuItem Text="Item2" Value="6"&gt;&lt;/RadzenMenuItem&gt;
/// &lt;/RadzenMenuItem&gt;
/// &lt;/RadzenMenuItem&gt;
/// &lt;/RadzenMenu&gt;);
///
/// void OnMenuItemClick(MenuItemEventArgs args)
/// {
/// Console.WriteLine($"Menu item with Value={args.Value} clicked");
/// }
/// }
/// </code>
/// </example>
public class ContextMenuService : IDisposable
{
/// <summary>
/// Gets or sets the navigation manager.
/// </summary>
/// <value>The navigation manager.</value>
NavigationManager navigationManager { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ContextMenuService"/> class.
/// </summary>
/// <param name="uriHelper">The URI helper.</param>
public ContextMenuService(NavigationManager uriHelper)
{
navigationManager = uriHelper;
@@ -21,6 +59,11 @@ namespace Radzen
}
}
/// <summary>
/// Handles the OnLocationChanged event of the UriHelper control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs"/> instance containing the event data.</param>
private void UriHelper_OnLocationChanged(object sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
{
if (this.OnNavigate != null)
@@ -29,12 +72,27 @@ namespace Radzen
}
}
/// <summary>
/// Occurs when [on navigate].
/// </summary>
public event Action OnNavigate;
/// <summary>
/// Raises the Close event.
/// </summary>
public event Action OnClose;
/// <summary>
/// Occurs when [on open].
/// </summary>
public event Action<MouseEventArgs, ContextMenuOptions> OnOpen;
/// <summary>
/// Opens the specified arguments.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
/// <param name="items">The items.</param>
/// <param name="click">The click.</param>
public void Open(MouseEventArgs args, IEnumerable<ContextMenuItem> items, Action<MenuItemEventArgs> click = null)
{
var options = new ContextMenuOptions();
@@ -45,6 +103,11 @@ namespace Radzen
OpenTooltip(args, options);
}
/// <summary>
/// Opens the specified arguments.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
/// <param name="childContent">Content of the child.</param>
public void Open(MouseEventArgs args, RenderFragment<ContextMenuService> childContent)
{
var options = new ContextMenuOptions();
@@ -54,39 +117,87 @@ namespace Radzen
OpenTooltip(args, options);
}
/// <summary>
/// Opens the tooltip.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
/// <param name="options">The options.</param>
private void OpenTooltip(MouseEventArgs args, ContextMenuOptions options)
{
OnOpen?.Invoke(args, options);
}
/// <summary>
/// Closes this instance.
/// </summary>
public void Close()
{
OnClose?.Invoke();
}
/// <summary>
/// Disposes this instance.
/// </summary>
public void Dispose()
{
navigationManager.LocationChanged -= UriHelper_OnLocationChanged;
}
}
/// <summary>
/// Class ContextMenuOptions.
/// </summary>
public class ContextMenuOptions
{
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
public RenderFragment<ContextMenuService> ChildContent { get; set; }
/// <summary>
/// Gets or sets the items.
/// </summary>
/// <value>The items.</value>
public IEnumerable<ContextMenuItem> Items { get; set; }
/// <summary>
/// Gets or sets the click.
/// </summary>
/// <value>The click.</value>
public Action<MenuItemEventArgs> Click { get; set; }
}
/// <summary>
/// Class ContextMenu.
/// </summary>
public class ContextMenu
{
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
public ContextMenuOptions Options { get; set; }
/// <summary>
/// Gets or sets the mouse event arguments.
/// </summary>
/// <value>The mouse event arguments.</value>
public MouseEventArgs MouseEventArgs { get; set; }
}
/// <summary>
/// Class ContextMenuItem.
/// </summary>
public class ContextMenuItem
{
{
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
public string Text { get; set; }
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
public object Value { get; set; }
}
}

View File

@@ -8,37 +8,85 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Radzen.Blazor;
using Radzen.Blazor.Rendering;
namespace Radzen
{
/// <summary>
/// Class DataBoundFormComponent.
/// Implements the <see cref="Radzen.RadzenComponent" />
/// Implements the <see cref="Radzen.IRadzenFormComponent" />
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="Radzen.RadzenComponent" />
/// <seealso cref="Radzen.IRadzenFormComponent" />
public class DataBoundFormComponent<T> : RadzenComponent, IRadzenFormComponent
{
/// <summary>
/// Gets or sets the index of the tab.
/// </summary>
/// <value>The index of the tab.</value>
[Parameter]
public int TabIndex { get; set; } = 0;
/// <summary>
/// Gets or sets the filter case sensitivity.
/// </summary>
/// <value>The filter case sensitivity.</value>
[Parameter]
public FilterCaseSensitivity FilterCaseSensitivity { get; set; } = FilterCaseSensitivity.Default;
/// <summary>
/// Gets or sets the filter operator.
/// </summary>
/// <value>The filter operator.</value>
[Parameter]
public StringFilterOperator FilterOperator { get; set; } = StringFilterOperator.Contains;
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[Parameter]
public string Name { get; set; }
/// <summary>
/// Gets or sets the placeholder.
/// </summary>
/// <value>The placeholder.</value>
[Parameter]
public string Placeholder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="DataBoundFormComponent{T}"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool Disabled { get; set; }
/// <summary>
/// Gets or sets the change.
/// </summary>
/// <value>The change.</value>
[Parameter]
public EventCallback<object> Change { get; set; }
/// <summary>
/// Gets or sets the load data.
/// </summary>
/// <value>The load data.</value>
[Parameter]
public EventCallback<Radzen.LoadDataArgs> LoadData { get; set; }
/// <summary>
/// The form
/// </summary>
IRadzenForm _form;
/// <summary>
/// Gets or sets the form.
/// </summary>
/// <value>The form.</value>
[CascadingParameter]
public IRadzenForm Form
{
@@ -48,15 +96,19 @@ namespace Radzen
}
set
{
if (_form != value && value != null)
{
_form = value;
_form.AddComponent(this);
}
_form = value;
_form?.AddComponent(this);
}
}
/// <summary>
/// The value
/// </summary>
object _value;
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Parameter]
public object Value
{
@@ -73,9 +125,17 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the value changed.
/// </summary>
/// <value>The value changed.</value>
[Parameter]
public EventCallback<T> ValueChanged { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is bound.
/// </summary>
/// <value><c>true</c> if this instance is bound; otherwise, <c>false</c>.</value>
public bool IsBound
{
get
@@ -83,7 +143,11 @@ namespace Radzen
return ValueChanged.HasDelegate;
}
}
public bool HasValue
/// <summary>
/// Gets a value indicating whether this instance has value.
/// </summary>
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
public virtual bool HasValue
{
get
{
@@ -95,10 +159,21 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the text property.
/// </summary>
/// <value>The text property.</value>
[Parameter]
public string TextProperty { get; set; }
/// <summary>
/// The data
/// </summary>
IEnumerable _data = null;
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
[Parameter]
public virtual IEnumerable Data
{
@@ -113,17 +188,23 @@ namespace Radzen
_view = null;
_value = null;
_data = value;
OnDataChanged();
StateHasChanged();
}
}
}
protected virtual void OnDataChanged()
/// <summary>
/// Called when [data changed].
/// </summary>
protected virtual async Task OnDataChanged()
{
await Task.CompletedTask;
}
/// <summary>
/// Gets the query.
/// </summary>
/// <value>The query.</value>
protected virtual IQueryable Query
{
get
@@ -132,9 +213,19 @@ namespace Radzen
}
}
protected string searchText;
/// <summary>
/// The search text
/// </summary>
internal string searchText;
/// <summary>
/// The view
/// </summary>
protected IQueryable _view = null;
/// <summary>
/// Gets the view.
/// </summary>
/// <value>The view.</value>
protected virtual IEnumerable View
{
get
@@ -171,15 +262,38 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the edit context.
/// </summary>
/// <value>The edit context.</value>
[CascadingParameter]
public EditContext EditContext { get; set; }
/// <summary>
/// Gets the field identifier.
/// </summary>
/// <value>The field identifier.</value>
public FieldIdentifier FieldIdentifier { get; private set; }
/// <summary>
/// Gets or sets the value expression.
/// </summary>
/// <value>The value expression.</value>
[Parameter]
public Expression<Func<T>> ValueExpression { get; set; }
public override Task SetParametersAsync(ParameterView parameters)
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
var dataChanged = parameters.DidParameterChange(nameof(Data), Data);
if (dataChanged)
{
await OnDataChanged();
}
var result = base.SetParametersAsync(parameters);
if (EditContext != null && ValueExpression != null && FieldIdentifier.Model != EditContext.Model)
@@ -188,14 +302,22 @@ namespace Radzen
EditContext.OnValidationStateChanged += ValidationStateChanged;
}
return result;
await result;
}
/// <summary>
/// Validations the state changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
{
StateHasChanged();
}
/// <summary>
/// Disposes this instance.
/// </summary>
public override void Dispose()
{
base.Dispose();
@@ -208,9 +330,23 @@ namespace Radzen
Form?.RemoveComponent(this);
}
/// <summary>
/// Gets the value.
/// </summary>
/// <returns>System.Object.</returns>
public object GetValue()
{
return Value;
}
/// <summary>
/// Gets the class list.
/// </summary>
/// <param name="className">Name of the class.</param>
/// <returns>ClassList.</returns>
protected ClassList GetClassList(string className) => ClassList.Create(className)
.AddDisabled(Disabled)
.Add(FieldIdentifier, EditContext);
}
}

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -6,13 +7,66 @@ using System.Threading.Tasks;
namespace Radzen
{
/// <summary>
/// Class DialogService. Contains various methods with options to open and close dialogs.
/// Should be added as scoped service in the application services and RadzenDialog should be added in application main layout.
/// </summary>
/// <example>
/// <code>
/// @inject DialogService DialogService
/// &lt;RadzenButton Text="Show dialog with inline Blazor content" Click=@ShowInlineDialog /&gt;
/// @code {
/// async Task ShowInlineDialog()
/// {
/// var result = await DialogService.OpenAsync("Simple Dialog", ds =&gt;
/// @&lt;div&gt;
/// &lt;p Style="margin-bottom: 1rem"&gt;Confirm?&lt;/p&gt;
/// &lt;div class="row"&gt;
/// &lt;div class="col-md-12"&gt;
/// &lt;RadzenButton Text="Ok" Click="() =&gt; ds.Close(true)" Style="margin-bottom: 10px; width: 150px" /&gt;
/// &lt;RadzenButton Text="Cancel" Click="() =&gt; ds.Close(false)" ButtonStyle="ButtonStyle.Secondary" Style="margin-bottom: 10px; width: 150px"/&gt;
/// &lt;RadzenButton Text="Refresh" Click="(() =&gt; { orderID = 10249; ds.Refresh(); })" ButtonStyle="ButtonStyle.Info" Style="margin-bottom: 10px; width: 150px"/&gt;
/// Order ID: @orderID
/// &lt;/div&gt;
/// &lt;/div&gt;
/// &lt;/div&gt;);
/// Console.WriteLine($"Dialog result: {result}");
/// }
/// }
/// </code>
/// </example>
public class DialogService : IDisposable
{
NavigationManager UriHelper { get; set; }
private DotNetObjectReference<DialogService> reference;
internal DotNetObjectReference<DialogService> Reference
{
get
{
if (reference == null)
{
reference = DotNetObjectReference.Create(this);
}
public DialogService(NavigationManager uriHelper)
return reference;
}
}
/// <summary>
/// Gets or sets the URI helper.
/// </summary>
/// <value>The URI helper.</value>
NavigationManager UriHelper { get; set; }
IJSRuntime JSRuntime { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="DialogService"/> class.
/// </summary>
/// <param name="uriHelper">The URI helper.</param>
/// <param name="jsRuntime">IJSRuntime instance.</param>
public DialogService(NavigationManager uriHelper, IJSRuntime jsRuntime)
{
UriHelper = uriHelper;
JSRuntime = jsRuntime;
if (UriHelper != null)
{
@@ -24,28 +78,58 @@ namespace Radzen
{
if (dialogs.Count > 0)
{
this.Close();
Close();
}
}
/// <summary>
/// Raises the Close event.
/// </summary>
public event Action<dynamic> OnClose;
/// <summary>
/// Occurs when [on refresh].
/// </summary>
public event Action OnRefresh;
/// <summary>
/// Occurs when a new dialog is open.
/// </summary>
public event Action<string, Type, Dictionary<string, object>, DialogOptions> OnOpen;
/// <summary>
/// Opens a dialog with the specified arguments.
/// </summary>
/// <typeparam name="T">The type of the Blazor component which will be displayed in a dialog.</typeparam>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T" />.</param>
/// <param name="options">The dialog options.</param>
public void Open<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
{
OpenDialog<T>(title, parameters, options);
}
/// <summary>
/// Invokes <see cref="OnRefresh" />.
/// </summary>
public void Refresh()
{
OnRefresh?.Invoke();
}
/// <summary>
/// The tasks
/// </summary>
protected List<TaskCompletionSource<dynamic>> tasks = new List<TaskCompletionSource<dynamic>>();
/// <summary>
/// Opens a dialog with the specified arguments.
/// </summary>
/// <typeparam name="T">The type of the Blazor component which will be displayed in a dialog.</typeparam>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T" />.</param>
/// <param name="options">The dialog options.</param>
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
public Task<dynamic> OpenAsync<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
{
var task = new TaskCompletionSource<dynamic>();
@@ -55,6 +139,14 @@ namespace Radzen
return task.Task;
}
/// <summary>
/// Opens a dialog with the specified content.
/// </summary>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="childContent">The content displayed in the dialog.</param>
/// <param name="options">The dialog options.</param>
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
public Task<dynamic> OpenAsync(string title, RenderFragment<DialogService> childContent, DialogOptions options = null)
{
var task = new TaskCompletionSource<dynamic>();
@@ -69,6 +161,12 @@ namespace Radzen
return task.Task;
}
/// <summary>
/// Opens a dialog with the specified content.
/// </summary>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="childContent">The content displayed in the dialog.</param>
/// <param name="options">The dialog options.</param>
public void Open(string title, RenderFragment<DialogService> childContent, DialogOptions options = null)
{
options = options ?? new DialogOptions();
@@ -78,7 +176,11 @@ namespace Radzen
OpenDialog<object>(title, null, options);
}
/// <summary>
/// The dialogs
/// </summary>
protected List<object> dialogs = new List<object>();
private void OpenDialog<T>(string title, Dictionary<string, object> parameters, DialogOptions options)
{
dialogs.Add(new object());
@@ -87,15 +189,25 @@ namespace Radzen
Width = options != null && !string.IsNullOrEmpty(options.Width) ? options.Width : "600px",
Left = options != null && !string.IsNullOrEmpty(options.Left) ? options.Left : "",
Top = options != null && !string.IsNullOrEmpty(options.Top) ? options.Top : "",
Bottom = options != null && !string.IsNullOrEmpty(options.Bottom) ? options.Bottom : "",
Height = options != null && !string.IsNullOrEmpty(options.Height) ? options.Height : "",
ShowTitle = options != null ? options.ShowTitle : true,
ShowClose = options != null ? options.ShowClose : true,
Resizable = options != null ? options.Resizable : false,
Draggable = options != null ? options.Draggable : false,
ChildContent = options?.ChildContent,
Style = options != null ? options.Style : "",
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
});
}
/// <summary>
/// Closes the last opened dialog with optional result.
/// </summary>
/// <param name="result">The result.</param>
[JSInvokable("DialogService.Close")]
public void Close(dynamic result = null)
{
var dialog = dialogs.LastOrDefault();
@@ -114,83 +226,198 @@ namespace Radzen
}
}
/// <inheritdoc />
public void Dispose()
{
UriHelper.LocationChanged -= UriHelper_OnLocationChanged;
}
public async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null) => await OpenAsync(title, ds => {
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.OpenElement(i++, "p");
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
b.AddContent(i++, message);
b.CloseElement();
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "row");
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "col-md-12");
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
b.AddAttribute(i++, "Style", "margin-bottom: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
b.CloseComponent();
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
b.AddAttribute(i++, "Style", "margin-bottom: 10px; margin-left: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
b.CloseComponent();
b.CloseElement();
b.CloseElement();
b.CloseElement();
};
return content;
}, new DialogOptions()
/// <summary>
/// Displays a confirmation dialog.
/// </summary>
/// <param name="message">The message displayed to the user.</param>
/// <param name="title">The text displayed in the title bar of the dialog.</param>
/// <param name="options">The options.</param>
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
public async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null)
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
Height = options != null ? options.Height : null,
Left = options != null ? options.Left : null,
Top = options != null ? options.Top : null,
Bottom = options != null ? options.Bottom : null,
ChildContent = options != null ? options.ChildContent : null,
ShowTitle = options != null ? options.ShowTitle : true,
ShowClose = options != null ? options.ShowClose : true,
Style = options != null ? options.Style : "",
});
var dialogOptions = new DialogOptions()
{
Width = options != null ? !string.IsNullOrEmpty(options.Width) ? options.Width : "355px" : "355px",
Height = options != null ? options.Height : null,
Left = options != null ? options.Left : null,
Top = options != null ? options.Top : null,
Bottom = options != null ? options.Bottom : null,
ChildContent = options != null ? options.ChildContent : null,
ShowTitle = options != null ? options.ShowTitle : true,
ShowClose = options != null ? options.ShowClose : true,
Resizable = options != null ? options.Resizable : false,
Draggable = options != null ? options.Draggable : false,
Style = options != null ? options.Style : "",
AutoFocusFirstElement = options != null ? options.AutoFocusFirstElement : true,
CloseDialogOnOverlayClick = options != null ? options.CloseDialogOnOverlayClick : false,
CloseDialogOnEsc = options != null ? options.CloseDialogOnEsc : true,
};
await JSRuntime.InvokeAsync<string>("Radzen.openDialog", dialogOptions, Reference);
return await OpenAsync(title, ds =>
{
RenderFragment content = b =>
{
var i = 0;
b.OpenElement(i++, "div");
b.OpenElement(i++, "p");
b.AddAttribute(i++, "style", "margin-bottom: 20px;");
b.AddContent(i++, message);
b.CloseElement();
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "row");
b.OpenElement(i++, "div");
b.AddAttribute(i++, "class", "col-md-12");
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.OkButtonText : "Ok");
b.AddAttribute(i++, "Style", "margin-bottom: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(true)));
b.CloseComponent();
b.OpenComponent<Blazor.RadzenButton>(i++);
b.AddAttribute(i++, "Text", options != null ? options.CancelButtonText : "Cancel");
b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Secondary);
b.AddAttribute(i++, "Style", "margin-bottom: 10px; margin-left: 10px; width: 150px");
b.AddAttribute(i++, "Click", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, () => ds.Close(false)));
b.CloseComponent();
b.CloseElement();
b.CloseElement();
b.CloseElement();
};
return content;
}, dialogOptions);
}
}
/// <summary>
/// Class DialogOptions.
/// </summary>
public class DialogOptions
{
/// <summary>
/// Gets or sets a value indicating whether to show the title bar. Set to <c>true</c> by default.
/// </summary>
/// <value><c>true</c> if title bar is shown; otherwise, <c>false</c>.</value>
public bool ShowTitle { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether to show the close button. Set to <c>true</c> by default.
/// </summary>
/// <value><c>true</c> if the close button is shown; otherwise, <c>false</c>.</value>
public bool ShowClose { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether the dialog is resizable. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
public bool Resizable { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether the dialog is draggable. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if draggable; otherwise, <c>false</c>.</value>
public bool Draggable { get; set; } = false;
/// <summary>
/// Gets or sets the X coordinate of the dialog. Maps to the <c>left</c> CSS attribute.
/// </summary>
/// <value>The left.</value>
public string Left { get; set; }
/// <summary>
/// Gets or sets the Y coordinate of the dialog. Maps to the <c>top</c> CSS attribute.
/// </summary>
/// <value>The top.</value>
public string Top { get; set; }
/// <summary>
/// Specifies the <c>bottom</c> CSS attribute.
/// </summary>
/// <value>The bottom.</value>
public string Bottom { get; set; }
/// <summary>
/// Gets or sets the width of the dialog.
/// </summary>
/// <value>The width.</value>
public string Width { get; set; }
/// <summary>
/// Gets or sets the height of the dialog.
/// </summary>
/// <value>The height.</value>
public string Height { get; set; }
/// <summary>
/// Gets or sets the CSS style of the dialog
/// </summary>
/// <value>The style.</value>
public string Style { get; set; }
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
public RenderFragment<DialogService> ChildContent { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to focus the first focusable HTML element. Set to <c>true</c> by default.
/// </summary>
public bool AutoFocusFirstElement { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether the dialog should be closed by clicking the overlay.
/// </summary>
/// <value><c>true</c> if closeable; otherwise, <c>false</c>.</value>
public bool CloseDialogOnOverlayClick { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether the dialog should be closed on ESC key press.
/// </summary>
/// <value><c>true</c> if closeable; otherwise, <c>false</c>.</value>
public bool CloseDialogOnEsc { get; set; } = true;
}
/// <summary>
/// Class ConfirmOptions.
/// </summary>
public class ConfirmOptions : DialogOptions
{
/// <summary>
/// Gets or sets the text of the OK button.
/// </summary>
public string OkButtonText { get; set; }
/// <summary>
/// Gets or sets the text of the Cancel button.
/// </summary>
public string CancelButtonText { get; set; }
}
/// <summary>
/// Class Dialog.
/// </summary>
public class Dialog
{
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
public string Title { get; set; }
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public Type Type { get; set; }
/// <summary>
/// Gets or sets the parameters.
/// </summary>
/// <value>The parameters.</value>
public Dictionary<string, object> Parameters { get; set; }
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
public DialogOptions Options { get; set; }
}
}

View File

@@ -3,58 +3,97 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.JSInterop;
using Radzen.Blazor;
namespace Radzen
{
/// <summary>
/// Base class of components that display a list of items.
/// </summary>
/// <typeparam name="T"></typeparam>
public class DropDownBase<T> : DataBoundFormComponent<T>
{
#if NET5
#if NET5_0_OR_GREATER
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object> virtualize;
/// <summary>
/// The Virtualize instance.
/// </summary>
public Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object> Virtualize
{
get
{
return virtualize;
}
}
List<object> virtualItems;
private async ValueTask<Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<object>> LoadItems(Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderRequest request)
{
var data = Data != null ? Data.Cast<object>() : Enumerable.Empty<object>();
var view = (LoadData.HasDelegate ? data : View).Cast<object>().AsQueryable();
var totalItemsCount = LoadData.HasDelegate ? Count : view.Count();
var top = Math.Min(request.Count, totalItemsCount - request.StartIndex);
var top = request.Count;
if(top <= 0)
{
top = PageSize;
}
if (LoadData.HasDelegate)
{
await LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = request.StartIndex, Top = top, Filter = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search) });
await LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = request.StartIndex, Top = request.Count, Filter = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search) });
}
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<object>(LoadData.HasDelegate ? Data.Cast<object>() : view.Skip(request.StartIndex).Take(top), totalItemsCount);
virtualItems = (LoadData.HasDelegate ? Data : view.Skip(request.StartIndex).Take(top)).Cast<object>().ToList();
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<object>(virtualItems, LoadData.HasDelegate ? Count : totalItemsCount);
}
/// <summary>
/// Specifies the total number of items in the data source.
/// </summary>
[Parameter]
public int Count { get; set; }
/// <summary>
/// Specifies wether virtualization is enabled. Set to <c>false</c> by default.
/// </summary>
[Parameter]
public bool AllowVirtualization { get; set; }
/// <summary>
/// Specifies the default page size. Set to <c>5</c> by default.
/// </summary>
[Parameter]
public int PageSize { get; set; } = 5;
#endif
/// <summary>
/// Determines whether virtualization is allowed.
/// </summary>
/// <returns><c>true</c> if virtualization is allowed; otherwise, <c>false</c>.</returns>
internal bool IsVirtualizationAllowed()
{
#if NET5
#if NET5_0_OR_GREATER
return AllowVirtualization;
#else
return false;
#endif
}
/// <summary>
/// Renders the items.
/// </summary>
/// <returns>RenderFragment.</returns>
internal virtual RenderFragment RenderItems()
{
return new RenderFragment(builder =>
{
#if NET5
#if NET5_0_OR_GREATER
if (AllowVirtualization)
{
builder.OpenComponent(0, typeof(Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object>));
@@ -87,32 +126,107 @@ namespace Radzen
});
}
/// <inheritdoc />
public override bool HasValue
{
get
{
if (typeof(T) == typeof(string))
{
return !string.IsNullOrEmpty($"{internalValue}");
}
return internalValue != null;
}
}
/// <summary>
/// Renders the item.
/// </summary>
/// <param name="builder">The builder.</param>
/// <param name="item">The item.</param>
internal virtual void RenderItem(RenderTreeBuilder builder, object item)
{
//
}
System.Collections.Generic.HashSet<object> keys = new System.Collections.Generic.HashSet<object>();
internal object GetKey(object item)
{
var value = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
if (!keys.Contains(value))
{
keys.Add(value);
return value;
}
else
{
return item;
}
}
/// <summary>
/// Gets or sets a value indicating whether filtering is allowed. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if filtering is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public virtual bool AllowFiltering { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user can clear the value. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if clearing is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowClear { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="DropDownBase{T}"/> is multiple.
/// </summary>
/// <value><c>true</c> if multiple; otherwise, <c>false</c>.</value>
[Parameter]
public bool Multiple { get; set; }
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment<dynamic> Template { get; set; }
/// <summary>
/// Gets or sets the value property.
/// </summary>
/// <value>The value property.</value>
[Parameter]
public string ValueProperty { get; set; }
/// <summary>
/// Gets or sets the disabled property.
/// </summary>
/// <value>The disabled property.</value>
[Parameter]
public string DisabledProperty { get; set; }
/// <summary>
/// Gets or sets the selected item changed.
/// </summary>
/// <value>The selected item changed.</value>
[Parameter]
public Action<object> SelectedItemChanged { get; set; }
protected List<object> selectedItems = new List<object>();
/// <summary>
/// The selected items
/// </summary>
protected IList<object> selectedItems = new List<object>();
/// <summary>
/// The selected item
/// </summary>
protected object selectedItem = null;
/// <summary>
/// Selects all.
/// </summary>
protected async System.Threading.Tasks.Task SelectAll()
{
if (Disabled)
@@ -133,27 +247,43 @@ namespace Radzen
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
Value = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
var type = typeof(T).IsGenericType ? typeof(T).GetGenericArguments()[0] : typeof(T);
Value = selectedItems.AsQueryable().Cast(type);
internalValue = selectedItems.AsQueryable().Cast(type);
}
await ValueChanged.InvokeAsync((T)Value);
await ValueChanged.InvokeAsync((T)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
StateHasChanged();
}
internal bool IsAllSelected()
{
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
{
return View != null && View.Cast<object>().All(i => IsItemSelectedByValue(PropertyAccess.GetValue(i, ValueProperty)));
}
return View != null && selectedItems.Count == View.Cast<object>().Count();
}
/// <summary>
/// Resets this instance.
/// </summary>
public void Reset()
{
InvokeAsync(ClearAll);
InvokeAsync(DebounceFilter);
}
/// <summary>
/// Clears all.
/// </summary>
protected async System.Threading.Tasks.Task ClearAll()
{
if (Disabled)
@@ -162,24 +292,31 @@ namespace Radzen
searchText = null;
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, "");
Value = default(T);
internalValue = default(T);
selectedItem = null;
selectedItems.Clear();
selectedIndex = -1;
await ValueChanged.InvokeAsync((T)Value);
await ValueChanged.InvokeAsync((T)internalValue);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
await OnFilter(new ChangeEventArgs());
StateHasChanged();
}
/// <summary>
/// The data
/// </summary>
IEnumerable _data;
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
[Parameter]
public override IEnumerable Data
{
@@ -200,8 +337,6 @@ namespace Radzen
selectedItems.Clear();
}
SelectItemFromValue(Value);
OnDataChanged();
StateHasChanged();
@@ -209,22 +344,34 @@ namespace Radzen
}
}
/// <summary>
/// Gets the popup identifier.
/// </summary>
/// <value>The popup identifier.</value>
protected string PopupID
{
get
{
return $"popup{UniqueID}";
return $"popup-{GetId()}";
}
}
/// <summary>
/// Gets the search identifier.
/// </summary>
/// <value>The search identifier.</value>
protected string SearchID
{
get
{
return $"search{UniqueID}";
return $"search-{GetId()}";
}
}
/// <summary>
/// Opens the popup script.
/// </summary>
/// <returns>System.String.</returns>
protected string OpenPopupScript()
{
if (Disabled)
@@ -235,6 +382,10 @@ namespace Radzen
return $"Radzen.togglePopup(this.parentNode, '{PopupID}', true);Radzen.focusElement('{SearchID}');";
}
/// <summary>
/// Opens the popup script from parent.
/// </summary>
/// <returns>System.String.</returns>
protected string OpenPopupScriptFromParent()
{
if (Disabled)
@@ -245,13 +396,32 @@ namespace Radzen
return $"Radzen.togglePopup(this, '{PopupID}', true);Radzen.focusElement('{SearchID}');";
}
/// <summary>
/// Gets or sets the filter delay.
/// </summary>
/// <value>The filter delay.</value>
[Parameter]
public int FilterDelay { get; set; } = 500;
/// <summary>
/// The search
/// </summary>
protected ElementReference search;
protected ElementReference list;
/// <summary>
/// The list
/// </summary>
protected ElementReference? list;
/// <summary>
/// The selected index
/// </summary>
protected int selectedIndex = -1;
/// <summary>
/// Opens the popup.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="isFilter">if set to <c>true</c> [is filter].</param>
/// <param name="isFromClick">if set to <c>true</c> [is from click].</param>
protected virtual async System.Threading.Tasks.Task OpenPopup(string key = "ArrowDown", bool isFilter = false, bool isFromClick = false)
{
if (Disabled)
@@ -260,15 +430,44 @@ namespace Radzen
await JSRuntime.InvokeVoidAsync("Radzen.togglePopup", Element, PopupID, true);
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", search, list, selectedIndex);
if (list != null)
{
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", search, list, selectedIndex);
}
}
/// <summary>
/// Handles the key press.
/// </summary>
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
/// <param name="isFilter">if set to <c>true</c> [is filter].</param>
private async System.Threading.Tasks.Task HandleKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args, bool isFilter = false)
{
if (Disabled)
return;
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>())).Cast<object>();
List<object> items = Enumerable.Empty<object>().ToList();
if (LoadData.HasDelegate)
{
if (Data != null)
{
items = Data.Cast<object>().ToList();
}
}
else
{
if (IsVirtualizationAllowed())
{
#if NET5_0_OR_GREATER
items = virtualItems;
#endif
}
else
{
items = View.Cast<object>().ToList();
}
}
var key = args.Code != null ? args.Code : args.Key;
@@ -276,11 +475,13 @@ namespace Radzen
{
try
{
var newSelectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown" || key == "ArrowRight", selectedIndex);
var currentViewIndex = Multiple ? selectedIndex : items.IndexOf(selectedItem);
var newSelectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown" || key == "ArrowRight", currentViewIndex);
if (!Multiple)
{
if (newSelectedIndex != selectedIndex && newSelectedIndex >= 0 && newSelectedIndex <= items.Count() - 1)
if (newSelectedIndex != currentViewIndex && newSelectedIndex >= 0 && newSelectedIndex <= items.Count() - 1)
{
selectedIndex = newSelectedIndex;
await OnSelectItem(items.ElementAt(selectedIndex), true);
@@ -288,7 +489,7 @@ namespace Radzen
}
else
{
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", selectedIndex);
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", currentViewIndex);
}
}
catch (Exception)
@@ -312,7 +513,7 @@ namespace Radzen
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
else if (key == "Delete")
else if (key == "Delete" && AllowClear)
{
if (!Multiple && selectedItem != null)
{
@@ -325,17 +526,24 @@ namespace Radzen
Debounce(DebounceFilter, FilterDelay);
}
}
else if(AllowFiltering && isFilter)
else if (AllowFiltering && isFilter)
{
Debounce(DebounceFilter, FilterDelay);
}
}
/// <summary>
/// Handles the <see cref="E:FilterKeyPress" /> event.
/// </summary>
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
protected virtual async System.Threading.Tasks.Task OnFilterKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)
{
await HandleKeyPress(args, true);
}
/// <summary>
/// Debounces the filter.
/// </summary>
async Task DebounceFilter()
{
if (!LoadData.HasDelegate)
@@ -344,13 +552,13 @@ namespace Radzen
_view = null;
if (IsVirtualizationAllowed())
{
#if NET5
#if NET5_0_OR_GREATER
if (virtualize != null)
{
await virtualize.RefreshDataAsync();
}
await InvokeAsync(() => { StateHasChanged(); });
#endif
#endif
}
else
{
@@ -361,41 +569,61 @@ namespace Radzen
{
if (IsVirtualizationAllowed())
{
#if NET5
#if NET5_0_OR_GREATER
if (virtualize != null)
{
await InvokeAsync(virtualize.RefreshDataAsync);
}
await InvokeAsync(() => { StateHasChanged(); });
#endif
#endif
}
else
{
await LoadData.InvokeAsync(await GetLoadDataArgs());
}
}
}
if (Multiple)
selectedIndex = -1;
await JSRuntime.InvokeAsync<string>("Radzen.repositionPopup", Element, PopupID);
}
/// <summary>
/// Handles the <see cref="E:KeyPress" /> event.
/// </summary>
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
protected async System.Threading.Tasks.Task OnKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)
{
await HandleKeyPress(args);
}
/// <summary>
/// Called when [select item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="isFromKey">if set to <c>true</c> [is from key].</param>
protected virtual async System.Threading.Tasks.Task OnSelectItem(object item, bool isFromKey = false)
{
await SelectItem(item);
}
/// <summary>
/// Handles the <see cref="E:Filter" /> event.
/// </summary>
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
protected virtual async System.Threading.Tasks.Task OnFilter(ChangeEventArgs args)
{
await DebounceFilter();
}
/// <summary>
/// Gets the load data arguments.
/// </summary>
/// <returns>LoadDataArgs.</returns>
internal virtual async System.Threading.Tasks.Task<LoadDataArgs> GetLoadDataArgs()
{
#if NET5
#if NET5_0_OR_GREATER
if (AllowVirtualization)
{
return new Radzen.LoadDataArgs() { Skip = 0, Top = PageSize, Filter = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search) };
@@ -409,8 +637,16 @@ namespace Radzen
#endif
}
/// <summary>
/// The first render
/// </summary>
private bool firstRender = true;
/// <summary>
/// Called when [after render asynchronous].
/// </summary>
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
/// <returns>Task.</returns>
protected override Task OnAfterRenderAsync(bool firstRender)
{
this.firstRender = firstRender;
@@ -418,8 +654,34 @@ namespace Radzen
return base.OnAfterRenderAsync(firstRender);
}
/// <inheritdoc />
protected override void OnInitialized()
{
internalValue = Value;
base.OnInitialized();
}
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
#if NET5_0_OR_GREATER
var pageSize = parameters.GetValueOrDefault<int>(nameof(PageSize));
if(pageSize != default(int))
{
PageSize = pageSize;
}
#endif
var selectedItemChanged = parameters.DidParameterChange(nameof(SelectedItem), SelectedItem);
if (selectedItemChanged)
{
await SelectItem(selectedItem, false);
}
var shouldClose = false;
if (parameters.DidParameterChange(nameof(Visible), Visible))
@@ -428,6 +690,11 @@ namespace Radzen
shouldClose = !visible;
}
if (parameters.DidParameterChange(nameof(Value), Value))
{
internalValue = parameters.GetValueOrDefault<object>(nameof(Value));
}
await base.SetParametersAsync(parameters);
if (shouldClose && !firstRender)
@@ -436,9 +703,13 @@ namespace Radzen
}
}
/// <summary>
/// Called when [parameters set asynchronous].
/// </summary>
/// <returns>Task.</returns>
protected override Task OnParametersSetAsync()
{
var valueAsEnumerable = Value as IEnumerable;
var valueAsEnumerable = internalValue as IEnumerable;
if (valueAsEnumerable != null)
{
@@ -448,28 +719,48 @@ namespace Radzen
}
}
SelectItemFromValue(Value);
SelectItemFromValue(internalValue);
return base.OnParametersSetAsync();
}
/// <summary>
/// Handles the <see cref="E:Change" /> event.
/// </summary>
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
protected void OnChange(ChangeEventArgs args)
{
Value = args.Value;
internalValue = args.Value;
}
/// <summary>
/// Determines whether the specified item is selected.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if the specified item is selected; otherwise, <c>false</c>.</returns>
internal bool isSelected(object item)
{
if (Multiple)
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
{
return selectedItems.IndexOf(item) != -1;
return IsItemSelectedByValue(PropertyAccess.GetValue(item, ValueProperty));
}
else
{
return item == selectedItem;
if (Multiple)
{
return selectedItems.IndexOf(item) != -1;
}
else
{
return item == selectedItem;
}
}
}
/// <summary>
/// Gets or sets the selected item.
/// </summary>
/// <value>The selected item.</value>
[Parameter]
public object SelectedItem
{
@@ -482,11 +773,14 @@ namespace Radzen
if (selectedItem != value)
{
selectedItem = object.Equals(value, "null") ? null : value;
SelectItem(selectedItem, false).Wait();
}
}
}
/// <summary>
/// Gets the items.
/// </summary>
/// <value>The items.</value>
protected virtual IEnumerable<object> Items
{
get
@@ -495,6 +789,10 @@ namespace Radzen
}
}
/// <summary>
/// Gets the view.
/// </summary>
/// <value>The view.</value>
protected override IEnumerable View
{
get
@@ -512,6 +810,11 @@ namespace Radzen
query.Add(TextProperty);
}
if (typeof(EnumerableQuery).IsAssignableFrom(Query.GetType()))
{
query.Add("ToString()");
}
if (ignoreCase)
{
query.Add("ToLower()");
@@ -529,7 +832,7 @@ namespace Radzen
}
else
{
_view = (typeof(IQueryable).IsAssignableFrom(Data.GetType())) ? Query.Cast<object>().ToList().AsQueryable() : Query;
_view = (typeof(IQueryable).IsAssignableFrom(Data.GetType())) ? (Query as IEnumerable).Cast<object>().ToList().AsQueryable() : Query;
}
}
}
@@ -538,6 +841,9 @@ namespace Radzen
}
}
/// <summary>
/// Sets the selected index from selected item.
/// </summary>
void SetSelectedIndexFromSelectedItem()
{
if (selectedItem != null)
@@ -557,12 +863,24 @@ namespace Radzen
}
}
/// <summary>
/// Selects the item internal.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="raiseChange">if set to <c>true</c> [raise change].</param>
internal async System.Threading.Tasks.Task SelectItemInternal(object item, bool raiseChange = true)
{
await SelectItem(item, raiseChange);
}
protected async System.Threading.Tasks.Task SelectItem(object item, bool raiseChange = true)
internal object internalValue;
/// <summary>
/// Selects the item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="raiseChange">if set to <c>true</c> [raise change].</param>
public async System.Threading.Tasks.Task SelectItem(object item, bool raiseChange = true)
{
if (!Multiple)
{
@@ -572,11 +890,11 @@ namespace Radzen
selectedItem = item;
if (!string.IsNullOrEmpty(ValueProperty))
{
Value = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
internalValue = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
}
else
{
Value = item;
internalValue = item;
}
SetSelectedIndexFromSelectedItem();
@@ -585,19 +903,35 @@ namespace Radzen
}
else
{
if (selectedItems.IndexOf(item) == -1)
if (!string.IsNullOrEmpty(ValueProperty))
{
selectedItems.Add(item);
if (LoadData.HasDelegate)
{
var v = PropertyAccess.GetValue(item, ValueProperty);
var si = (selectedItems ?? Enumerable.Empty<object>()).AsQueryable().Where($@"object.Equals({ValueProperty},@0)", v).FirstOrDefault();
if (si == null)
{
selectedItems.Add(item);
}
else
{
selectedItems.Remove(si);
}
}
else
{
UpdateSelectedItems(item);
}
}
else
{
selectedItems.Remove(item);
UpdateSelectedItems(item);
}
if (!string.IsNullOrEmpty(ValueProperty))
{
System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
Value = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
}
else
{
@@ -605,23 +939,44 @@ namespace Radzen
var elementType = firstElement != null ? firstElement.GetType() : null;
if (elementType != null)
{
Value = selectedItems.AsQueryable().Cast(elementType);
internalValue = selectedItems.AsQueryable().Cast(elementType);
}
else
{
Value = selectedItems;
internalValue = selectedItems;
}
}
}
if (raiseChange)
{
await ValueChanged.InvokeAsync(object.Equals(Value, null) ? default(T) : (T)Value);
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(object.Equals(internalValue, null) ? default(T) : (T)internalValue);
}
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
await Change.InvokeAsync(internalValue);
}
StateHasChanged();
}
internal void UpdateSelectedItems(object item)
{
if (selectedItems.IndexOf(item) == -1)
{
selectedItems.Add(item);
}
else
{
selectedItems.Remove(item);
}
}
/// <summary>
/// Selects the item from value.
/// </summary>
/// <param name="value">The value.</param>
protected virtual void SelectItemFromValue(object value)
{
if (value != null && View != null)
@@ -641,7 +996,7 @@ namespace Radzen
}
else
{
selectedItem = Value;
selectedItem = internalValue;
}
SetSelectedIndexFromSelectedItem();
@@ -650,12 +1005,12 @@ namespace Radzen
}
else
{
var values = value as dynamic;
var values = value as IEnumerable;
if (values != null)
{
if (!string.IsNullOrEmpty(ValueProperty))
{
foreach (object v in values)
foreach (object v in values.ToDynamicList())
{
dynamic item;
@@ -668,7 +1023,7 @@ namespace Radzen
item = View.AsQueryable().Where($@"{ValueProperty} == @0", v).FirstOrDefault();
}
if (item != null && selectedItems.IndexOf(item) == -1)
if (!object.Equals(item, null) && (LoadData.HasDelegate ? !IsItemSelectedByValue(v) : selectedItems.IndexOf(item) == -1))
{
selectedItems.Add(item);
}
@@ -687,5 +1042,19 @@ namespace Radzen
selectedItem = null;
}
}
internal bool IsItemSelectedByValue(object v)
{
return ((Multiple ? selectedItems : selectedItem != null ? new[] { selectedItem } : Enumerable.Empty<object>()) ?? Enumerable.Empty<object>())
.AsQueryable().Where($@"object.Equals({ValueProperty},@0)", v).Any();
}
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
keys.Clear();
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
namespace Radzen.Blazor
{
/// <summary>
/// Class EnumExtensions.
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// Gets enum description.
/// </summary>
public static string GetDisplayDescription(this Enum enumValue)
{
var enumValueAsString = enumValue.ToString();
var val = enumValue.GetType().GetMember(enumValueAsString).FirstOrDefault();
return val?.GetCustomAttribute<DisplayAttribute>()?.GetDescription() ?? enumValueAsString;
}
/// <summary>
/// Converts Enum to IEnumerable of Value/Text.
/// </summary>
public static IEnumerable<object> EnumAsKeyValuePair(Type enumType)
{
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ToInt32(val), Text = val.GetDisplayDescription() });
}
}
}

View File

@@ -5,28 +5,64 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor.Rendering;
namespace Radzen
{
/// <summary>
/// Class FormComponent.
/// Implements the <see cref="Radzen.RadzenComponent" />
/// Implements the <see cref="Radzen.IRadzenFormComponent" />
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="Radzen.RadzenComponent" />
/// <seealso cref="Radzen.IRadzenFormComponent" />
public class FormComponent<T> : RadzenComponent, IRadzenFormComponent
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[Parameter]
public string Name { get; set; }
/// <summary>
/// Gets or sets the index of the tab.
/// </summary>
/// <value>The index of the tab.</value>
[Parameter]
public int TabIndex { get; set; } = 0;
/// <summary>
/// Gets or sets the placeholder.
/// </summary>
/// <value>The placeholder.</value>
[Parameter]
public string Placeholder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="FormComponent{T}"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool Disabled { get; set; }
/// <summary>
/// The form
/// </summary>
IRadzenForm _form;
/// <summary>
/// Gets or sets the edit context.
/// </summary>
/// <value>The edit context.</value>
[CascadingParameter]
public EditContext EditContext { get; set; }
/// <summary>
/// Gets or sets the form.
/// </summary>
/// <value>The form.</value>
[CascadingParameter]
public IRadzenForm Form
{
@@ -36,17 +72,22 @@ namespace Radzen
}
set
{
if (_form != value && value != null)
{
_form = value;
_form.AddComponent(this);
}
_form = value;
_form?.AddComponent(this);
}
}
/// <summary>
/// Gets or sets the value changed.
/// </summary>
/// <value>The value changed.</value>
[Parameter]
public EventCallback<T> ValueChanged { get; set; }
/// <summary>
/// Gets a value indicating whether this instance has value.
/// </summary>
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
public virtual bool HasValue
{
get
@@ -59,6 +100,10 @@ namespace Radzen
}
}
/// <summary>
/// Gets a value indicating whether this instance is bound.
/// </summary>
/// <value><c>true</c> if this instance is bound; otherwise, <c>false</c>.</value>
public bool IsBound
{
get
@@ -67,8 +112,15 @@ namespace Radzen
}
}
/// <summary>
/// The value
/// </summary>
protected T _value;
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Parameter]
public virtual T Value
{
@@ -86,11 +138,28 @@ namespace Radzen
}
/// <summary>
/// Gets or sets the change.
/// </summary>
/// <value>The change.</value>
[Parameter]
public EventCallback<T> Change { get; set; }
/// <summary>
/// Gets the field identifier.
/// </summary>
/// <value>The field identifier.</value>
public FieldIdentifier FieldIdentifier { get; private set; }
/// <summary>
/// Gets or sets the value expression.
/// </summary>
/// <value>The value expression.</value>
[Parameter]
public Expression<Func<T>> ValueExpression { get; set; }
/// <summary>
/// Sets the parameters asynchronous.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>Task.</returns>
public override Task SetParametersAsync(ParameterView parameters)
{
var result = base.SetParametersAsync(parameters);
@@ -98,17 +167,26 @@ namespace Radzen
if (EditContext != null && ValueExpression != null && FieldIdentifier.Model != EditContext.Model)
{
FieldIdentifier = FieldIdentifier.Create(ValueExpression);
EditContext.OnValidationStateChanged -= ValidationStateChanged;
EditContext.OnValidationStateChanged += ValidationStateChanged;
}
return result;
}
/// <summary>
/// Validations the state changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
{
StateHasChanged();
}
/// <summary>
/// Disposes this instance.
/// </summary>
public override void Dispose()
{
base.Dispose();
@@ -121,11 +199,20 @@ namespace Radzen
Form?.RemoveComponent(this);
}
/// <summary>
/// Gets the value.
/// </summary>
/// <returns>System.Object.</returns>
public object GetValue()
{
return Value;
}
/// <summary>
/// Handles the <see cref="E:ContextMenu" /> event.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
/// <returns>Task.</returns>
public override Task OnContextMenu(MouseEventArgs args)
{
if (!Disabled)
@@ -135,5 +222,14 @@ namespace Radzen
return Task.CompletedTask;
}
/// <summary>
/// Gets the class list.
/// </summary>
/// <param name="className">Name of the class.</param>
/// <returns>ClassList.</returns>
protected ClassList GetClassList(string className) => ClassList.Create(className)
.AddDisabled(Disabled)
.Add(FieldIdentifier, EditContext);
}
}

View File

@@ -6,21 +6,49 @@ using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
/// <summary>
/// Class GaugeBase.
/// Implements the <see cref="Radzen.RadzenComponent" />
/// </summary>
/// <seealso cref="Radzen.RadzenComponent" />
public abstract class GaugeBase : RadzenComponent
{
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent
{
get; set;
}
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>The width.</value>
public double? Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
public double? Height { get; set; }
/// <summary>
/// The width and height are set
/// </summary>
bool widthAndHeightAreSet = false;
/// <summary>
/// The first render
/// </summary>
bool firstRender = true;
/// <summary>
/// On after render as an asynchronous operation.
/// </summary>
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
/// <returns>A Task representing the asynchronous operation.</returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
this.firstRender = firstRender;
@@ -43,6 +71,9 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Called when [initialized].
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
@@ -50,6 +81,11 @@ namespace Radzen.Blazor
Initialize();
}
/// <summary>
/// Resizes the specified width.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
[JSInvokable]
public void Resize(double width, double height)
{
@@ -73,6 +109,9 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Initializes this instance.
/// </summary>
private void Initialize()
{
double width = 0;
@@ -107,8 +146,16 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// The visible changed
/// </summary>
private bool visibleChanged = false;
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
@@ -131,6 +178,9 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Disposes this instance.
/// </summary>
public override void Dispose()
{
base.Dispose();
@@ -141,6 +191,9 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Reloads this instance.
/// </summary>
public void Reload()
{
StateHasChanged();

View File

@@ -1,9 +1,21 @@
namespace Radzen.Blazor
{
/// <summary>
/// Enum GaugeTickPosition
/// </summary>
public enum GaugeTickPosition
{
/// <summary>
/// The inside
/// </summary>
Inside,
/// <summary>
/// The outside
/// </summary>
Outside,
/// <summary>
/// The none
/// </summary>
None
}
}

View File

@@ -7,8 +7,21 @@ using System.Xml.Linq;
namespace Radzen
{
/// <summary>
/// Class HttpResponseMessageExtensions.
/// </summary>
public static class HttpResponseMessageExtensions
{
/// <summary>
/// Read as an asynchronous operation.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="response">The response.</param>
/// <returns>A Task&lt;T&gt; representing the asynchronous operation.</returns>
/// <exception cref="Exception">Unable to parse the response.</exception>
/// <exception cref="Exception"></exception>
/// <exception cref="Exception">Unable to parse the response.</exception>
/// <exception cref="Exception"></exception>
public static async Task<T> ReadAsync<T>(this HttpResponseMessage response)
{
try

View File

@@ -1,7 +1,13 @@
namespace Radzen.Blazor
{
/// <summary>
/// Common axis API of <see cref="RadzenChart" />
/// </summary>
public interface IChartAxis
{
/// <summary>
/// Gets or sets the grid lines configuration of this axis.
/// </summary>
RadzenGridLines GridLines { get; set; }
}
}

View File

@@ -1,7 +1,14 @@
namespace Radzen.Blazor
{
/// <summary>
/// Marker interface for <see cref="RadzenBarSeries{TItem}" />.
/// </summary>
public interface IChartBarSeries
{
/// <summary>
/// Gets the count.
/// </summary>
/// <value>The count.</value>
int Count { get; }
}
}

View File

@@ -1,7 +1,14 @@
namespace Radzen.Blazor
{
/// <summary>
/// Marker interface for <see cref="RadzenColumnSeries{TItem}" />.
/// </summary>
public interface IChartColumnSeries
{
/// <summary>
/// Gets the count.
/// </summary>
/// <value>The count.</value>
int Count { get; }
}
}

View File

@@ -2,8 +2,17 @@ using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Marker interface for <see cref="RadzenColumnSeries{TItem}" />.
/// </summary>
public interface IChartDonutSeries
{
RenderFragment RenderTitle(double x, double y);
/// <summary>
/// Renders the title.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>RenderFragment.</returns>
RenderFragment RenderTitle(double x, double y);
}
}

View File

@@ -1,24 +1,149 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
namespace Radzen.Blazor
{
/// <summary>
/// Specifies the common API that <see cref="RadzenChart" /> series must implement.
/// </summary>
public interface IChartSeries
{
/// <summary>
/// Transforms a category scale to new one.
/// </summary>
/// <param name="scale">The scale.</param>
ScaleBase TransformCategoryScale(ScaleBase scale);
/// <summary>
/// Transforms a category scale to new one.
/// </summary>
/// <param name="scale">The scale.</param>
ScaleBase TransformValueScale(ScaleBase scale);
/// <summary>
/// Gets or sets the series marker configuration.
/// </summary>
RadzenMarkers Markers { get; set; }
/// <summary>
/// Gets the series marker type.
/// </summary>
/// <value>The type of the marker.</value>
MarkerType MarkerType { get; }
/// <summary>
/// Gets the size of the marker.
/// </summary>
/// <value>The size of the marker.</value>
double MarkerSize { get; }
/// <summary>
/// Renders the series with the specified category and value scales.
/// </summary>
/// <param name="categoryScale">The category scale.</param>
/// <param name="valueScale">The value scale.</param>
/// <returns>RenderFragment.</returns>
RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
/// <summary>
/// Renders the series overlays with the specified category and value scales.
/// </summary>
/// <param name="categoryScale">The category scale.</param>
/// <param name="valueScale">The value scale.</param>
/// <returns>RenderFragment.</returns>
RenderFragment RenderOverlays(ScaleBase categoryScale, ScaleBase valueScale);
/// <summary>
/// Renders the series tooltip.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="marginLeft">The left margin.</param>
/// <param name="marginTop">The right margin.</param>
/// <returns>RenderFragment.</returns>
RenderFragment RenderTooltip(object data, double marginLeft, double marginTop);
/// <summary>
/// Renders the legend item.
/// </summary>
/// <returns>RenderFragment.</returns>
RenderFragment RenderLegendItem();
/// <summary>
/// Gets the color.
/// </summary>
/// <value>The color.</value>
string Color { get; }
bool Visible { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="IChartSeries"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
bool Visible { get; }
/// <summary>
/// Gets a value indicating whether this series should appear in the legend.
/// </summary>
/// <value><c>true</c> if the series appears in the legend; otherwise, <c>false</c>.</value>
bool ShowInLegend { get; }
/// <summary>
/// Gets or sets the rendering order.
/// </summary>
/// <value>The rendering order.</value>
int RenderingOrder { get; set; }
bool Contains(double x, double y);
/// <summary>
/// Determines if the series contains the specified coordinates with a given tolerance.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns><c>true</c> if the series contains the coordinates; otherwise, <c>false</c>.</returns>
bool Contains(double x, double y, double tolerance);
/// <summary>
/// Returns the data at the specified coordinates;
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
object DataAt(double x, double y);
/// <summary>
/// Returns data chart position
/// </summary>
IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY);
/// <summary>
/// Returns series median
/// </summary>
double GetMedian();
/// <summary>
/// Returns series mean
/// </summary>
double GetMean();
/// <summary>
/// Returns series mode
/// </summary>
double GetMode();
/// <summary>
/// Returns series trend
/// </summary>
(double a, double b) GetTrend();
/// <summary>
/// Series coordinate system
/// </summary>
CoordinateSystem CoordinateSystem { get; }
/// <summary>
/// Series overlays
/// </summary>
IList<IChartSeriesOverlay> Overlays{ get; }
/// <summary>
/// Gets or sets the title of the series. The title is displayed in tooltips and the legend.
/// </summary>
/// <value>The title.</value>
string Title { get; set; }
/// <summary>
/// Gets the title.
/// </summary>
string GetTitle();
/// <summary>
/// Measures the legend.
/// </summary>
/// <returns>System.Double.</returns>
double MeasureLegend();
/// <summary>
/// Invokes the click handler with the provided data item.
/// </summary>
/// <param name="handler">The handler.</param>
/// <param name="data">The data.</param>
Task InvokeClick(EventCallback<SeriesClickEventArgs> handler, object data);
}
}

View File

@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Interface for chart overlays
/// </summary>
public interface IChartSeriesOverlay
{
/// <summary>
/// Render overlay
/// </summary>
/// <param name="categoryScale"></param>
/// <param name="valueScale"></param>
/// <returns>RenderFragment</returns>
RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale);
/// <summary>
/// Gets overlay visibility state
/// </summary>
bool Visible { get; }
/// <summary>
/// Hit test
/// </summary>
bool Contains(double mouseX, double mouseY, int tolerance);
/// <summary>
/// Renders tooltip
/// </summary>
RenderFragment RenderTooltip(double mouseX, double mouseY, double marginLeft, double marginTop);
}
}

View File

@@ -1,23 +1,95 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// The common <see cref="RadzenScheduler{TItem}" /> API injected as a cascading parameter to is views.
/// </summary>
public interface IScheduler
{
/// <summary>
/// Gets the appointments in the specified range.
/// </summary>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <returns>A collection of appointments within the specified range.</returns>
IEnumerable<AppointmentData> GetAppointmentsInRange(DateTime start, DateTime end);
/// <summary>
/// Determines whether an appointment is within the specified range.
/// </summary>
/// <param name="item">The appointment to check.</param>
/// <param name="start">The start of the range.</param>
/// <param name="end">The end of the range.</param>
/// <returns><c>true</c> if the appointment is within the specified range; otherwise, <c>false</c>.</returns>
bool IsAppointmentInRange(AppointmentData item, DateTime start, DateTime end);
/// <summary>
/// Adds a view. Must be called when a <see cref="ISchedulerView" /> is initialized.
/// </summary>
/// <param name="view">The view to add.</param>
Task AddView(ISchedulerView view);
/// <summary>
/// Removes a view. Must be called when a <see cref="ISchedulerView" /> is disposed.
/// </summary>
/// <param name="view">The view to remove.</param>
void RemoveView(ISchedulerView view);
/// <summary>
/// Determines whether the specified view is selected.
/// </summary>
/// <param name="view">The view.</param>
/// <returns><c>true</c> if the specified view is selected; otherwise, <c>false</c>.</returns>
bool IsSelected(ISchedulerView view);
/// <summary>
/// Gets or sets the current date.
/// </summary>
/// <value>The current date.</value>
DateTime CurrentDate { get; set; }
/// <summary>
/// Selects the specified appointment.
/// </summary>
/// <param name="data">The appointment to select.</param>
Task SelectAppointment(AppointmentData data);
/// <summary>
/// Selects the specified slot.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
Task SelectSlot(DateTime start, DateTime end);
/// <summary>
/// Gets the appointment HTML attributes.
/// </summary>
/// <param name="item">The appointment.</param>
/// <returns>A dictionary containing the HTML attributes for the specified appointment.</returns>
IDictionary<string, object> GetAppointmentAttributes(AppointmentData item);
/// <summary>
/// Gets the slot HTML attributes.
/// </summary>
/// <param name="start">The start of the slot.</param>
/// <param name="end">The end of the slot.</param>
/// <returns>A dictionary containing the HTML attributes for the specified slot.</returns>
IDictionary<string, object> GetSlotAttributes(DateTime start, DateTime end);
/// <summary>
/// Renders the appointment.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>RenderFragment.</returns>
RenderFragment RenderAppointment(AppointmentData item);
/// <summary>
/// Reloads this instance.
/// </summary>
Task Reload();
/// <summary>
/// Gets the height.
/// </summary>
/// <value>The height.</value>
double Height { get; }
/// <summary>
/// Gets or sets the culture.
/// </summary>
/// <value>The culture.</value>
CultureInfo Culture { get; set; }
}
}

View File

@@ -3,18 +3,51 @@ using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Interface that has to be implemented by a view in order to by supported by <see cref="RadzenScheduler{TItem}" />.
/// </summary>
public interface ISchedulerView
{
/// <summary>
/// Gets the icon of the view. It is displayed in the view switching UI.
/// </summary>
string Icon { get; }
/// <summary>
/// Gets the title of the view. It is displayed in the RadzenScheduler title area.
/// </summary>
/// <value>The title.</value>
string Title { get; }
/// <summary>
/// Gets the text of the view. It is displayed in the view switching UI.
/// </summary>
/// <value>The text.</value>
string Text { get; }
/// <summary>
/// Returns a new date when the user clicks the next button of RadzenScheduler.
/// </summary>
/// <returns>The next date. For example a day view will return the next day, a week view will return the next week.</returns>
DateTime Next();
/// <summary>
/// Returns a new date when the user clicks the previous button of RadzenScheduler.
/// </summary>
/// <returns>The previous date. For example a day view will return the previous day, a week view will return the previous week.</returns>
DateTime Prev();
/// <summary>
/// Renders this instance.
/// </summary>
/// <returns>RenderFragment.</returns>
RenderFragment Render();
/// <summary>
/// Gets the start date.
/// </summary>
DateTime StartDate { get; }
/// <summary>
/// Gets the end date.
/// </summary>
DateTime EndDate { get; }
}
}

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018-2021 Radzen Ltd
Copyright (c) 2018-2022 Radzen Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,10 +1,25 @@
namespace Radzen.Blazor
{
/// <summary>
/// Specifies the legend position in a <see cref="RadzenChart" />.
/// </summary>
public enum LegendPosition
{
/// <summary>
/// The legend is at the right side of the series.
/// </summary>
Right,
/// <summary>
/// The legend is at the left side of the series.
/// </summary>
Left,
/// <summary>
/// The legend is above the series.
/// </summary>
Top,
/// <summary>
/// The legend is below the series.
/// </summary>
Bottom
}
}

View File

@@ -1,9 +1,21 @@
namespace Radzen.Blazor
{
/// <summary>
/// Specified the line drawing style.
/// </summary>
public enum LineType
{
/// <summary>
/// Solid lines.
/// </summary>
Solid,
/// <summary>
/// Dashed lines.
/// </summary>
Dashed,
/// <summary>
/// Dotted lines.
/// </summary>
Dotted
}
}

View File

@@ -65,7 +65,7 @@ namespace Radzen.Blazor
if (start == end)
{
start = 0;
end = end + NiceNumber(end/ticks, false);
end = end + NiceNumber(end / ticks, false);
}
var range = end - start;

View File

@@ -1,12 +1,33 @@
namespace Radzen.Blazor
{
/// <summary>
/// Specifies the type of marker that <see cref="RadzenChart" /> displays for data points.
/// </summary>
public enum MarkerType
{
/// <summary>
/// Do not display a marker for data points.
/// </summary>
None,
/// <summary>
/// Cycle between markers.
/// </summary>
Auto,
/// <summary>
/// Use a circle marker.
/// </summary>
Circle,
/// <summary>
/// Use a triangle marker.
/// </summary>
Triangle,
/// <summary>
/// Use a square marker.
/// </summary>
Square,
/// <summary>
/// Use a diamond marker.
/// </summary>
Diamond
}
}

View File

@@ -5,10 +5,28 @@ using System.Text;
namespace Radzen
{
/// <summary>
/// Class NotificationService. Contains various methods with options to open notifications.
/// Should be added as scoped service in the application services and RadzenNotification should be added in application main layout.
/// </summary>
/// <example>
/// <code>
/// @inject NotificationService NotificationService
/// &lt;RadzenButton Text="Show info notification" Click=@(args => NotificationService.Notify(new NotificationMessage { Severity = NotificationSeverity.Info, Summary = "Info Summary", Detail = "Info Detail", Duration = 4000 })) / &gt;
/// </code>
/// </example>
public class NotificationService
{
/// <summary>
/// Gets the messages.
/// </summary>
/// <value>The messages.</value>
public ObservableCollection<NotificationMessage> Messages { get; private set; } = new ObservableCollection<NotificationMessage>();
/// <summary>
/// Notifies the specified message.
/// </summary>
/// <param name="message">The message.</param>
public void Notify(NotificationMessage message)
{
var newMessage = new NotificationMessage()
@@ -26,6 +44,13 @@ namespace Radzen
}
}
/// <summary>
/// Notifies the specified severity.
/// </summary>
/// <param name="severity">The severity.</param>
/// <param name="summary">The summary.</param>
/// <param name="detail">The detail.</param>
/// <param name="duration">The duration.</param>
public void Notify(NotificationSeverity severity = NotificationSeverity.Info, string summary = "", string detail = "", double duration = 3000)
{
var newMessage = new NotificationMessage()
@@ -43,12 +68,35 @@ namespace Radzen
}
}
/// <summary>
/// Class NotificationMessage.
/// </summary>
public class NotificationMessage
{
/// <summary>
/// Gets or sets the duration.
/// </summary>
/// <value>The duration.</value>
public double? Duration { get; set; }
/// <summary>
/// Gets or sets the severity.
/// </summary>
/// <value>The severity.</value>
public NotificationSeverity Severity { get; set; }
/// <summary>
/// Gets or sets the summary.
/// </summary>
/// <value>The summary.</value>
public string Summary { get; set; }
/// <summary>
/// Gets or sets the detail.
/// </summary>
/// <value>The detail.</value>
public string Detail { get; set; }
/// <summary>
/// Gets or sets the style.
/// </summary>
/// <value>The style.</value>
public string Style { get; set; }
}
}

View File

@@ -8,35 +8,76 @@ using System.Web;
namespace Radzen
{
/// <summary>
/// Class ODataEnumerable.
/// Implements the <see cref="IEnumerable{T}" />
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="IEnumerable{T}" />
public class ODataEnumerable<T> : IEnumerable<T>
{
/// <summary>
/// The source
/// </summary>
IEnumerable<T> source;
/// <summary>
/// Initializes a new instance of the <see cref="ODataEnumerable{T}"/> class.
/// </summary>
/// <param name="source">The source.</param>
public ODataEnumerable(IEnumerable<T> source)
{
this.source = source;
}
/// <summary>
/// Gets the enumerator.
/// </summary>
/// <returns>IEnumerator&lt;T&gt;.</returns>
public IEnumerator<T> GetEnumerator()
{
return source.GetEnumerator();
}
/// <summary>
/// Gets the enumerator.
/// </summary>
/// <returns>IEnumerator.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return source.GetEnumerator();
}
}
/// <summary>
/// Class ODataServiceResult.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ODataServiceResult<T>
{
/// <summary>
/// Gets or sets the count.
/// </summary>
/// <value>The count.</value>
[JsonPropertyName("@odata.count")]
public int Count { get; set; }
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
public IEnumerable<T> Value { get; set; }
}
/// <summary>
/// Class ODataJsonSerializer.
/// </summary>
public static class ODataJsonSerializer
{
/// <summary>
/// Determines whether the specified type is complex.
/// </summary>
/// <param name="type">The type.</param>
/// <returns><c>true</c> if the specified type is complex; otherwise, <c>false</c>.</returns>
static bool IsComplex(Type type)
{
var underlyingType = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(type) : type;
@@ -47,11 +88,23 @@ namespace Radzen
type != typeof(string) && type != typeof(decimal) && type.IsClass;
}
/// <summary>
/// Determines whether the specified type is enumerable.
/// </summary>
/// <param name="type">The type.</param>
/// <returns><c>true</c> if the specified type is enumerable; otherwise, <c>false</c>.</returns>
static bool IsEnumerable(Type type)
{
return !typeof(string).IsAssignableFrom(type) && (typeof(IEnumerable<>).IsAssignableFrom(type) || typeof(IEnumerable).IsAssignableFrom(type));
}
/// <summary>
/// Serializes the specified value.
/// </summary>
/// <typeparam name="TValue">The type of the t value.</typeparam>
/// <param name="value">The value.</param>
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)
{
if (options == null)
@@ -70,19 +123,45 @@ namespace Radzen
}
}
/// <summary>
/// Class ComplexPropertiesConverter.
/// Implements the <see cref="JsonConverter{T}" />
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="JsonConverter{T}" />
public class ComplexPropertiesConverter<T> : JsonConverter<T>
{
/// <summary>
/// The complex properties
/// </summary>
IEnumerable<string> complexProperties;
/// <summary>
/// Initializes a new instance of the <see cref="ComplexPropertiesConverter{T}"/> class.
/// </summary>
/// <param name="complexProperties">The complex properties.</param>
public ComplexPropertiesConverter(IEnumerable<string> complexProperties)
{
this.complexProperties = complexProperties;
}
/// <summary>
/// Reads the specified reader.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="typeToConvert">The type to convert.</param>
/// <param name="options">The options.</param>
/// <returns>T.</returns>
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonSerializer.Deserialize<T>(ref reader, options);
}
/// <summary>
/// Writes the specified writer.
/// </summary>
/// <param name="writer">The writer.</param>
/// <param name="value">The value.</param>
/// <param name="options">The options.</param>
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
writer.WriteStartObject();
@@ -105,21 +184,54 @@ namespace Radzen
}
}
/// <summary>
/// Class DateTimeConverterUsingDateTimeParse.
/// Implements the <see cref="JsonConverter{DateTime}" />
/// </summary>
/// <seealso cref="JsonConverter{DateTime}" />
public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
{
/// <summary>
/// Reads the specified reader.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="typeToConvert">The type to convert.</param>
/// <param name="options">The options.</param>
/// <returns>DateTime.</returns>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.Parse(reader.GetString());
}
/// <summary>
/// Writes the specified writer.
/// </summary>
/// <param name="writer">The writer.</param>
/// <param name="value">The value.</param>
/// <param name="options">The options.</param>
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
}
}
/// <summary>
/// Class ODataExtensions.
/// </summary>
public static class ODataExtensions
{
{
/// <summary>
/// Gets the o data URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="filter">The filter.</param>
/// <param name="top">The top.</param>
/// <param name="skip">The skip.</param>
/// <param name="orderby">The orderby.</param>
/// <param name="expand">The expand.</param>
/// <param name="select">The select.</param>
/// <param name="count">if set to <c>true</c> [count].</param>
/// <returns>Uri.</returns>
public static Uri GetODataUri(this Uri uri, string filter = null, int? top = null, int? skip = null, string orderby = null, string expand = null, string select = null, bool? count = null)
{
var uriBuilder = new UriBuilder(uri);

View File

@@ -8,29 +8,93 @@ using Radzen.Blazor;
namespace Radzen
{
/// <summary>
/// Base classes of components that support paging.
/// </summary>
/// <typeparam name="T">The type of the data item</typeparam>
public class PagedDataBoundComponent<T> : RadzenComponent
{
/// <summary>
/// Gets or sets the pager position. Set to <c>PagerPosition.Bottom</c> by default.
/// </summary>
/// <value>The pager position.</value>
[Parameter]
public PagerPosition PagerPosition { get; set; } = PagerPosition.Bottom;
/// <summary>
/// Gets or sets a value indicating whether pager is visible even when not enough data for paging.
/// </summary>
/// <value><c>true</c> if pager is visible even when not enough data for paging otherwise, <c>false</c>.</value>
[Parameter]
public bool PagerAlwaysVisible { get; set; }
/// <summary>
/// Gets or sets the horizontal align.
/// </summary>
/// <value>The horizontal align.</value>
[Parameter]
public HorizontalAlign PagerHorizontalAlign { get; set; } = HorizontalAlign.Justify;
/// <summary>
/// Gets or sets a value indicating whether paging is allowed. Set to <c>false</c> by default.
/// </summary>
/// <value><c>true</c> if paging is allowed; otherwise, <c>false</c>.</value>
[Parameter]
public bool AllowPaging { get; set; }
int _PageSize = 10;
/// <summary>
/// Gets or sets the size of the page.
/// </summary>
/// <value>The size of the page.</value>
[Parameter]
public int PageSize { get; set; } = 10;
public int PageSize
{
get
{
return pageSize ?? _PageSize;
}
set
{
_PageSize = value;
}
}
/// <summary>
/// Gets or sets the page numbers count.
/// </summary>
/// <value>The page numbers count.</value>
[Parameter]
public int PageNumbersCount { get; set; } = 5;
/// <summary>
/// Gets or sets the count.
/// </summary>
/// <value>The count.</value>
[Parameter]
public int Count { get; set; }
/// <summary>
/// Gets or sets the current page.
/// </summary>
/// <value>The current page.</value>
public int CurrentPage { get; set; }
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment<T> Template { get; set; }
/// <summary>
/// The data
/// </summary>
IEnumerable<T> _data;
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
[Parameter]
public IEnumerable<T> Data
{
@@ -49,22 +113,58 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the page size options.
/// </summary>
/// <value>The page size options.</value>
[Parameter]
public IEnumerable<int> PageSizeOptions { get; set; }
/// <summary>
/// Gets or sets the page size description text.
/// </summary>
/// <value>The page size description text.</value>
[Parameter]
public string PageSizeText { get; set; } = "items per page";
/// <summary>
/// Gets or sets the pager summary visibility.
/// </summary>
/// <value>The pager summary visibility.</value>
[Parameter]
public bool ShowPagingSummary { get; set; } = false;
/// <summary>
/// Gets or sets the pager summary format.
/// </summary>
/// <value>The pager summary format.</value>
[Parameter]
public string PagingSummaryFormat { get; set; } = "Page {0} of {1} ({2} items)";
/// <summary>
/// The view
/// </summary>
protected IQueryable<T> _view = null;
/// <summary>
/// Gets the paged view.
/// </summary>
/// <value>The paged view.</value>
public virtual IQueryable<T> PagedView
{
get
{
if (_view == null)
{
_view = (AllowPaging ? View.Skip(skip).Take(PageSize) : View).ToList().AsQueryable();
_view = (AllowPaging && !LoadData.HasDelegate ? View.Skip(skip).Take(PageSize) : View).ToList().AsQueryable();
}
return _view;
}
}
/// <summary>
/// Gets the view.
/// </summary>
/// <value>The view.</value>
public virtual IQueryable<T> View
{
get
@@ -73,9 +173,16 @@ namespace Radzen
}
}
/// <summary>
/// Gets or sets the load data.
/// </summary>
/// <value>The load data.</value>
[Parameter]
public EventCallback<Radzen.LoadDataArgs> LoadData { get; set; }
/// <summary>
/// Reloads this instance.
/// </summary>
public async virtual Task Reload()
{
_view = null;
@@ -95,14 +202,23 @@ namespace Radzen
}
}
/// <summary>
/// Called when [data changed].
/// </summary>
protected virtual void OnDataChanged()
{
}
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
bool pageSizeChanged = parameters.DidParameterChange(nameof(PageSize), PageSize);
bool pageSizeChanged = parameters.DidParameterChange(nameof(PageSize), PageSize) &&
PageSize != pageSize;
await base.SetParametersAsync(parameters);
@@ -112,6 +228,10 @@ namespace Radzen
}
}
/// <summary>
/// Called when [parameters set asynchronous].
/// </summary>
/// <returns>Task.</returns>
protected override Task OnParametersSetAsync()
{
if (Visible && !LoadData.HasDelegate)
@@ -126,50 +246,105 @@ namespace Radzen
return base.OnParametersSetAsync();
}
/// <summary>
/// The first render
/// </summary>
bool firstRender = true;
protected override Task OnAfterRenderAsync(bool firstRender)
/// <summary>
/// Called when [after render asynchronous].
/// </summary>
/// <param name="firstRender">if set to <c>true</c> [first render].</param>
/// <returns>Task.</returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
this.firstRender = firstRender;
if (firstRender && Visible && (LoadData.HasDelegate && Data == null))
if (firstRender)
{
InvokeAsync(Reload);
StateHasChanged();
await ReloadOnFirstRender();
}
return base.OnAfterRenderAsync(firstRender);
await base.OnAfterRenderAsync(firstRender);
}
internal virtual async Task ReloadOnFirstRender()
{
if (firstRender && Visible && (LoadData.HasDelegate && Data == null))
{
await InvokeAsync(Reload);
StateHasChanged();
}
}
/// <summary>
/// The skip
/// </summary>
protected int skip;
/// <summary>
/// The top pager
/// </summary>
protected RadzenPager topPager;
/// <summary>
/// The bottom pager
/// </summary>
protected RadzenPager bottomPager;
/// <summary>
/// Gets or sets the page callback.
/// </summary>
/// <value>The page callback.</value>
[Parameter]
public EventCallback<PagerEventArgs> Page { get; set; }
/// <summary>
/// Handles the <see cref="E:PageChanged" /> event.
/// </summary>
/// <param name="args">The <see cref="PagerEventArgs"/> instance containing the event data.</param>
protected async Task OnPageChanged(PagerEventArgs args)
{
skip = args.Skip;
CurrentPage = args.PageIndex;
await Page.InvokeAsync(args);
await InvokeAsync(Reload);
}
int? pageSize;
/// <summary>
/// Called when [page size changed].
/// </summary>
/// <param name="value">The value.</param>
protected async Task OnPageSizeChanged(int value)
{
PageSize = value;
pageSize = value;
await InvokeAsync(Reload);
}
/// <summary>
/// Calculates the pager.
/// </summary>
protected void CalculatePager()
{
if (topPager != null)
{
topPager.SetCount(Count);
topPager.SetCurrentPage(CurrentPage);
}
if (bottomPager != null)
{
bottomPager.SetCount(Count);
bottomPager.SetCurrentPage(CurrentPage);
}
}
/// <summary>
/// Goes to page.
/// </summary>
/// <param name="page">The page.</param>
public async Task GoToPage(int page)
{
if (topPager != null)
@@ -183,19 +358,33 @@ namespace Radzen
}
}
/// <summary>
/// Firsts the page.
/// </summary>
/// <param name="forceReload">if set to <c>true</c> [force reload].</param>
public async Task FirstPage(bool forceReload = false)
{
var shouldReload = forceReload && CurrentPage == 0;
if (topPager != null)
{
await topPager.FirstPage(forceReload);
await topPager.FirstPage();
}
if (bottomPager != null)
{
await bottomPager.FirstPage(forceReload);
await bottomPager.FirstPage();
}
if (shouldReload)
{
await InvokeAsync(Reload);
}
}
/// <summary>
/// Previouses the page.
/// </summary>
public async Task PrevPage()
{
if (topPager != null)
@@ -209,6 +398,9 @@ namespace Radzen
}
}
/// <summary>
/// Nexts the page.
/// </summary>
public async Task NextPage()
{
if (topPager != null)
@@ -222,6 +414,9 @@ namespace Radzen
}
}
/// <summary>
/// Lasts the page.
/// </summary>
public async Task LastPage()
{
if (topPager != null)

View File

@@ -7,8 +7,14 @@ using System.Linq.Dynamic.Core;
namespace Radzen
{
/// <summary>
/// Class QueryableExtension.
/// </summary>
public static class QueryableExtension
{
/// <summary>
/// The filter operators
/// </summary>
internal static readonly IDictionary<string, string> FilterOperators = new Dictionary<string, string>
{
{"eq", "="},
@@ -19,9 +25,13 @@ namespace Radzen
{"ge", ">="},
{"startswith", "StartsWith"},
{"endswith", "EndsWith"},
{"contains", "Contains"}
{"contains", "Contains"},
{"DoesNotContain", "Contains"}
};
/// <summary>
/// The linq filter operators
/// </summary>
internal static readonly IDictionary<FilterOperator, string> LinqFilterOperators = new Dictionary<FilterOperator, string>
{
{FilterOperator.Equals, "="},
@@ -32,9 +42,17 @@ namespace Radzen
{FilterOperator.GreaterThanOrEquals, ">="},
{FilterOperator.StartsWith, "StartsWith"},
{FilterOperator.EndsWith, "EndsWith"},
{FilterOperator.Contains, "Contains"}
{FilterOperator.Contains, "Contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "=="},
{FilterOperator.IsEmpty, "=="},
{FilterOperator.IsNotNull, "!="},
{FilterOperator.IsNotEmpty, "!="}
};
/// <summary>
/// The o data filter operators
/// </summary>
internal static readonly IDictionary<FilterOperator, string> ODataFilterOperators = new Dictionary<FilterOperator, string>
{
{FilterOperator.Equals, "eq"},
@@ -45,9 +63,19 @@ namespace Radzen
{FilterOperator.GreaterThanOrEquals, "ge"},
{FilterOperator.StartsWith, "startswith"},
{FilterOperator.EndsWith, "endswith"},
{FilterOperator.Contains, "contains"}
{FilterOperator.Contains, "contains"},
{FilterOperator.DoesNotContain, "DoesNotContain"},
{FilterOperator.IsNull, "eq"},
{FilterOperator.IsEmpty, "eq"},
{FilterOperator.IsNotNull, "ne"},
{FilterOperator.IsNotEmpty, "ne"}
};
/// <summary>
/// Converts to list.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>IList.</returns>
public static IList ToList(IQueryable query)
{
var genericToList = typeof(Enumerable).GetMethod("ToList")
@@ -55,6 +83,12 @@ namespace Radzen
return (IList)genericToList.Invoke(null, new[] { query });
}
/// <summary>
/// Converts to filterstring.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="columns">The columns.</param>
/// <returns>System.String.</returns>
public static string ToFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
{
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
@@ -101,10 +135,19 @@ namespace Radzen
return "";
}
/// <summary>
/// Converts to filterstring.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="columns">The columns.</param>
/// <returns>System.String.</returns>
public static string ToFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) || c.GetFilterOperator() == FilterOperator.IsNotNull
|| c.GetFilterOperator() == FilterOperator.IsNull || c.GetFilterOperator() == FilterOperator.IsEmpty
|| c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -117,10 +160,11 @@ namespace Radzen
string value = "";
string secondValue = "";
var v = column.GetFilterValue();
var sv = column.GetSecondFilterValue();
if (PropertyAccess.IsDate(column.FilterPropertyType))
{
var v = column.GetFilterValue();
var sv = column.GetSecondFilterValue();
if (v != null)
{
value = v is DateTime ? ((DateTime)v).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : v is DateTimeOffset ? ((DateTimeOffset)v).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : "";
@@ -130,13 +174,74 @@ namespace Radzen
secondValue = sv is DateTime ? ((DateTime)sv).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : sv is DateTimeOffset ? ((DateTimeOffset)sv).UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") : "";
}
}
else if (PropertyAccess.IsEnum(column.FilterPropertyType) || PropertyAccess.IsNullableEnum(column.FilterPropertyType))
{
if (v != null)
{
value = ((int)v).ToString();
}
if (sv != null)
{
secondValue = ((int)sv).ToString();
}
}
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
{
var enumerableValue = ((IEnumerable)(v != null ? v : Enumerable.Empty<object>())).AsQueryable();
var enumerableSecondValue = ((IEnumerable)(sv != null ? sv : Enumerable.Empty<object>())).AsQueryable();
var enumerableValueAsString = "new []{" + String.Join(",",
(enumerableValue.ElementType == typeof(string) ? enumerableValue.Cast<string>().Select(i => $@"""{i}""").Cast<object>() : enumerableValue.Cast<object>())) + "}";
var enumerableSecondValueAsString = "new []{" + String.Join(",",
(enumerableSecondValue.ElementType == typeof(string) ? enumerableSecondValue.Cast<string>().Select(i => $@"""{i}""").Cast<object>() : enumerableSecondValue.Cast<object>())) + "}";
if (enumerableValue != null)
{
var columnFilterOperator = column.GetFilterOperator();
var columnSecondFilterOperator = column.GetSecondFilterOperator();
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
{
linqOperator = "==";
}
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
if (property.IndexOf(".") != -1)
{
property = $"({property})";
}
if (sv == null)
{
if (columnFilterOperator == FilterOperator.Contains || columnFilterOperator == FilterOperator.DoesNotContain)
{
whereList.Add($@"{(columnFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableValueAsString}).Contains({property})");
}
}
else
{
if ((columnFilterOperator == FilterOperator.Contains || columnFilterOperator == FilterOperator.DoesNotContain) &&
(columnSecondFilterOperator == FilterOperator.Contains || columnSecondFilterOperator == FilterOperator.DoesNotContain))
{
whereList.Add($@"{(columnFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableValueAsString}).Contains({property}) {booleanOperator} {(columnSecondFilterOperator == FilterOperator.DoesNotContain ? "!" : "")}({enumerableSecondValueAsString}).Contains({property})");
}
}
}
}
else
{
value = (string)Convert.ChangeType(column.GetFilterValue(), typeof(string));
secondValue = (string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
}
if (!string.IsNullOrEmpty(value))
if (!string.IsNullOrEmpty(value) || column.GetFilterOperator() == FilterOperator.IsNotNull
|| column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty
|| column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
var linqOperator = LinqFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -163,6 +268,13 @@ namespace Radzen
return "";
}
/// <summary>
/// Gets the column filter.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column">The column.</param>
/// <param name="second">if set to <c>true</c> [second].</param>
/// <returns>System.String.</returns>
private static string GetColumnFilter<T>(RadzenGridColumn<T> column, bool second = false)
{
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
@@ -215,6 +327,10 @@ namespace Radzen
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
{
return $@"({property} == null ? """" : !{property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.StartsWith(""{value}""{filterCaseSensitivityOperator})";
@@ -244,6 +360,14 @@ namespace Radzen
return "";
}
/// <summary>
/// Gets the column filter.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column">The column.</param>
/// <param name="value">The value.</param>
/// <param name="second">if set to <c>true</c> [second].</param>
/// <returns>System.String.</returns>
private static string GetColumnFilter<T>(RadzenDataGridColumn<T> column, string value, bool second = false)
{
var property = PropertyAccess.GetProperty(column.GetFilterProperty());
@@ -269,6 +393,10 @@ namespace Radzen
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.DoesNotContain)
{
return $@"!({property} == null ? """" : {property}){filterCaseSensitivityOperator}.Contains(""{value}""{filterCaseSensitivityOperator})";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.StartsWith)
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator}.StartsWith(""{value}""{filterCaseSensitivityOperator})";
@@ -285,22 +413,60 @@ namespace Radzen
{
return $@"({property} == null ? """" : {property}){filterCaseSensitivityOperator} != ""{value}""{filterCaseSensitivityOperator}";
}
else if (columnFilterOperator == FilterOperator.IsNull)
{
return $@"np({property}) == null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty)
{
return $@"np({property}) == ''";
}
else if (columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $@"np({property}) != ''";
}
else if (columnFilterOperator == FilterOperator.IsNotNull)
{
return $@"np({property}) != null";
}
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
return $"{property} {linqOperator} {value}";
if (column.GetFilterOperator() == FilterOperator.IsNull || column.GetFilterOperator() == FilterOperator.IsNotNull)
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
return $"{property} {linqOperator} {value}";
}
}
else if (column.FilterPropertyType == typeof(DateTime) ||
column.FilterPropertyType == typeof(DateTime?) ||
column.FilterPropertyType == typeof(DateTimeOffset) ||
column.FilterPropertyType == typeof(DateTimeOffset?))
{
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ssZ";
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
if (column.GetFilterOperator() == FilterOperator.IsNull || column.GetFilterOperator() == FilterOperator.IsNotNull)
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
var dateTimeValue = DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind);
var finalDate = dateTimeValue.TimeOfDay == TimeSpan.Zero ? dateTimeValue.Date : dateTimeValue;
var dateFormat = dateTimeValue.TimeOfDay == TimeSpan.Zero ? "yyyy-MM-dd" : "yyyy-MM-ddTHH:mm:ssZ";
var dateFunction = column.FilterPropertyType == typeof(DateTimeOffset) || column.FilterPropertyType == typeof(DateTimeOffset?) ? "DateTimeOffset" : "DateTime";
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat)}"")";
return $@"{property} {linqOperator} {dateFunction}(""{finalDate.ToString(dateFormat)}"")";
}
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
{
@@ -308,12 +474,30 @@ namespace Radzen
}
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
{
return $@"{property} {linqOperator} Guid(""{value}"")";
if (column.GetFilterOperator() == FilterOperator.IsNull || column.GetFilterOperator() == FilterOperator.IsNotNull)
{
return $"{property} {linqOperator} null";
}
else if (column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
return $"{property} {linqOperator} ''";
}
else
{
return $@"{property} {linqOperator} Guid(""{value}"")";
}
}
return "";
}
/// <summary>
/// Gets the column o data filter.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column">The column.</param>
/// <param name="second">if set to <c>true</c> [second].</param>
/// <returns>System.String.</returns>
private static string GetColumnODataFilter<T>(RadzenGridColumn<T> column, bool second = false)
{
var columnType = column.Type;
@@ -351,6 +535,12 @@ namespace Radzen
$"contains({property}, tolower('{value}'))" :
$"contains({property}, '{value}')";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "DoesNotContain")
{
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
$"not(contains({property}, tolower('{value}')))" :
$"not(contains({property}, '{value}'))";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == "startswith")
{
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
@@ -388,14 +578,23 @@ namespace Radzen
return "";
}
/// <summary>
/// Gets the column o data filter.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column">The column.</param>
/// <param name="second">if set to <c>true</c> [second].</param>
/// <returns>System.String.</returns>
private static string GetColumnODataFilter<T>(RadzenDataGridColumn<T> column, bool second = false)
{
var property = column.GetFilterProperty().Replace('.', '/');
var columnFilterOperator = !second ? column.GetFilterOperator() : column.GetSecondFilterOperator();
var odataFilterOperator = ODataFilterOperators[columnFilterOperator];
var value = !second ? (string)Convert.ChangeType(column.GetFilterValue(), typeof(string)) :
(string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
var value = IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) ? null :
!second ? (string)Convert.ChangeType(column.GetFilterValue(), typeof(string)) :
(string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
if (column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive && column.FilterPropertyType == typeof(string))
{
@@ -410,6 +609,12 @@ namespace Radzen
$"contains({property}, tolower('{value}'))" :
$"contains({property}, '{value}')";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.DoesNotContain)
{
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
$"not(contains({property}, tolower('{value}')))" :
$"not(contains({property}, '{value}'))";
}
else if (!string.IsNullOrEmpty(value) && columnFilterOperator == FilterOperator.StartsWith)
{
return column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ?
@@ -434,30 +639,84 @@ namespace Radzen
$"{property} ne tolower('{value}')" :
$"{property} ne '{value}'";
}
else if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
}
else if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string))
{
var v = !second ? column.GetFilterValue() : column.GetSecondFilterValue();
var enumerableValue = ((IEnumerable)(v != null ? v : Enumerable.Empty<object>())).AsQueryable();
var enumerableValueAsString = "(" + String.Join(",",
(enumerableValue.ElementType == typeof(string) ? enumerableValue.Cast<string>().Select(i => $@"'{i}'").Cast<object>() : enumerableValue.Cast<object>())) + ")";
if (enumerableValue.Any() && columnFilterOperator == FilterOperator.Contains)
{
return $"{property} in {enumerableValueAsString}";
}
else if (enumerableValue.Any() && columnFilterOperator == FilterOperator.DoesNotContain)
{
return $"not({property} in {enumerableValueAsString})";
}
}
else if (PropertyAccess.IsNumeric(column.FilterPropertyType))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {value}";
return $"{property} {odataFilterOperator} {value}";
}
else if (column.FilterPropertyType == typeof(bool) || column.FilterPropertyType == typeof(bool?))
{
return $"{property} eq {value.ToLower()}";
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
else
{
return $"{property} eq {value.ToLower()}";
}
}
else if (column.FilterPropertyType == typeof(DateTime) ||
column.FilterPropertyType == typeof(DateTime?) ||
column.FilterPropertyType == typeof(DateTimeOffset) ||
column.FilterPropertyType == typeof(DateTimeOffset?))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
if (columnFilterOperator == FilterOperator.IsNull || columnFilterOperator == FilterOperator.IsNotNull)
{
return $"{property} {odataFilterOperator} null";
}
else if (columnFilterOperator == FilterOperator.IsEmpty || columnFilterOperator == FilterOperator.IsNotEmpty)
{
return $"{property} {odataFilterOperator} ''";
}
else
{
return $"{property} {odataFilterOperator} {DateTime.Parse(value, null, System.Globalization.DateTimeStyles.RoundtripKind).ToString("yyyy-MM-ddTHH:mm:ss.fffZ")}";
}
}
else if (column.FilterPropertyType == typeof(Guid) || column.FilterPropertyType == typeof(Guid?))
{
return $"{property} {ODataFilterOperators[columnFilterOperator]} {value}";
return $"{property} {odataFilterOperator} {value}";
}
return "";
}
/// <summary>
/// Converts to odatafilterstring.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="columns">The columns.</param>
/// <returns>System.String.</returns>
public static string ToODataFilterString<T>(this IEnumerable<RadzenGridColumn<T>> columns)
{
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
@@ -506,10 +765,19 @@ namespace Radzen
return "";
}
/// <summary>
/// Converts to odatafilterstring.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="columns">The columns.</param>
/// <returns>System.String.</returns>
public static string ToODataFilterString<T>(this IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -521,10 +789,11 @@ namespace Radzen
{
var property = column.GetFilterProperty().Replace('.', '/');
var value = (string)Convert.ChangeType(column.GetFilterValue(), typeof(string));
var secondValue = (string)Convert.ChangeType(column.GetSecondFilterValue(), typeof(string));
var value = column.GetFilterValue();
var secondValue = column.GetSecondFilterValue();
if (!string.IsNullOrEmpty(value))
if (value != null || column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty)
{
var linqOperator = ODataFilterOperators[column.GetFilterOperator()];
if (linqOperator == null)
@@ -534,12 +803,12 @@ namespace Radzen
var booleanOperator = column.LogicalFilterOperator == LogicalFilterOperator.And ? "and" : "or";
if (string.IsNullOrEmpty(secondValue))
if (secondValue == null)
{
whereList.Add(GetColumnODataFilter(column));
}
else
{
{
whereList.Add($"({GetColumnODataFilter(column)} {booleanOperator} {GetColumnODataFilter(column, true)})");
}
}
@@ -551,6 +820,13 @@ namespace Radzen
return "";
}
/// <summary>
/// Wheres the specified columns.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="columns">The columns.</param>
/// <returns>IQueryable&lt;T&gt;.</returns>
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenGridColumn<T>> columns)
{
Func<RadzenGridColumn<T>, bool> canFilter = (c) => c.Filterable && !string.IsNullOrEmpty(c.Type) &&
@@ -591,6 +867,11 @@ namespace Radzen
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
index++;
}
else if (comparison == "DoesNotContain")
{
whereList.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})", new object[] { column.FilterValue });
index++;
}
else
{
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.FilterValue });
@@ -601,12 +882,14 @@ namespace Radzen
{
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
comparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
index++;
var secondComparison = FilterOperators[column.SecondFilterOperator];
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
secondComparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
index++;
@@ -620,10 +903,25 @@ namespace Radzen
return source;
}
private static bool IsEnumerable(Type type)
{
return typeof(IEnumerable).IsAssignableFrom(type) || typeof(IEnumerable<>).IsAssignableFrom(type);
}
/// <summary>
/// Wheres the specified columns.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="columns">The columns.</param>
/// <returns>IQueryable&lt;T&gt;.</returns>
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<RadzenDataGridColumn<T>> columns)
{
Func<RadzenDataGridColumn<T>, bool> canFilter = (c) => c.Filterable && c.FilterPropertyType != null &&
!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty) && c.GetFilterProperty() != null;
(!(c.GetFilterValue() == null || c.GetFilterValue() as string == string.Empty)
|| c.GetFilterOperator() == FilterOperator.IsNotNull || c.GetFilterOperator() == FilterOperator.IsNull
|| c.GetFilterOperator() == FilterOperator.IsEmpty || c.GetFilterOperator() == FilterOperator.IsNotEmpty)
&& c.GetFilterProperty() != null;
if (columns.Where(canFilter).Any())
{
@@ -641,13 +939,18 @@ namespace Radzen
property = $"({property})";
}
if (column.FilterPropertyType == typeof(string))
if (column.FilterPropertyType == typeof(string) &&
!(column.GetFilterOperator() == FilterOperator.IsNotNull || column.GetFilterOperator() == FilterOperator.IsNull
|| column.GetFilterOperator() == FilterOperator.IsEmpty || column.GetFilterOperator() == FilterOperator.IsNotEmpty))
{
property = $@"({property} == null ? """" : {property})";
}
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string) &&
column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
string filterCaseSensitivityOperator = column.FilterPropertyType == typeof(string)
&& column.GetFilterOperator() != FilterOperator.IsNotNull && column.GetFilterOperator() != FilterOperator.IsNull
&& column.GetFilterOperator() != FilterOperator.IsEmpty && column.GetFilterOperator() != FilterOperator.IsNotEmpty
&& column.Grid.FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
var comparison = LinqFilterOperators[column.GetFilterOperator()];
@@ -657,10 +960,31 @@ namespace Radzen
{
if (comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains")
{
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "Contains")
{
whereList.Add($@"(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
}
else
{
whereList.Add($@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
}
index++;
}
else
else if (comparison == "DoesNotContain")
{
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) && comparison == "DoesNotContain")
{
whereList.Add($@"!(@{index}).Contains({property})", new object[] { column.GetFilterValue() });
}
else
{
whereList.Add($@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})", new object[] { column.GetFilterValue() });
}
index++;
}
else if (!(IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string)))
{
whereList.Add($@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}", new object[] { column.GetFilterValue() });
index++;
@@ -668,32 +992,65 @@ namespace Radzen
}
else
{
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
index++;
var secondComparison = LinqFilterOperators[column.GetSecondFilterOperator()];
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
index++;
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.GetFilterValue(), column.GetSecondFilterValue() });
if (IsEnumerable(column.FilterPropertyType) && column.FilterPropertyType != typeof(string) &&
(comparison == "Contains" || comparison == "DoesNotContain") &&
(secondComparison == "Contains" || secondComparison == "DoesNotContain"))
{
var firstFilter = $@"{(comparison == "DoesNotContain" ? "!" : "")}(@{index}).Contains({property})";
index++;
var secondFilter = $@"{(secondComparison == "DoesNotContain" ? "!" : "")}(@{index}).Contains({property})";
index++;
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.GetFilterValue(), column.GetSecondFilterValue() });
}
else
{
var firstFilter = comparison == "StartsWith" || comparison == "EndsWith" || comparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{comparison}(@{index}{filterCaseSensitivityOperator})" :
comparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {comparison} @{index}{filterCaseSensitivityOperator}";
index++;
var secondFilter = secondComparison == "StartsWith" || secondComparison == "EndsWith" || secondComparison == "Contains" ?
$@"{property}{filterCaseSensitivityOperator}.{secondComparison}(@{index}{filterCaseSensitivityOperator})" :
secondComparison == "DoesNotContain" ? $@"!{property}{filterCaseSensitivityOperator}.Contains(@{index}{filterCaseSensitivityOperator})" :
$@"{property}{filterCaseSensitivityOperator} {secondComparison} @{index}{filterCaseSensitivityOperator}";
index++;
whereList.Add($@"({firstFilter} {booleanOperator} {secondFilter})", new object[] { column.GetFilterValue(), column.GetSecondFilterValue() });
}
}
}
return source.Where(string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray());
return whereList.Keys.Any() ?
source.Where(string.Join($" {gridBooleanOperator} ", whereList.Keys), whereList.Values.SelectMany(i => i.ToArray()).ToArray())
: source;
}
return source;
}
/// <summary>
/// Ases the o data enumerable.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <returns>ODataEnumerable&lt;T&gt;.</returns>
public static ODataEnumerable<T> AsODataEnumerable<T>(this IEnumerable<T> source)
{
return new ODataEnumerable<T>(source);
}
/// <summary>
/// Selects the many recursive.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <returns>IEnumerable&lt;T&gt;.</returns>
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
var result = source.SelectMany(selector);

View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<NoWarn>BL9993</NoWarn>
<TargetFrameworks>netstandard2.1;net5.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1;net5.0;net6.0</TargetFrameworks>
<RazorLangVersion>3.0</RazorLangVersion>
<LangVersion>7.3</LangVersion>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<PackageId>Radzen.Blazor</PackageId>
<Product>Radzen.Blazor</Product>
<Version>3.6.4</Version>
<Version>3.20.3</Version>
<Copyright>Radzen Ltd.</Copyright>
<Authors>Radzen Ltd.</Authors>
<Description>Native Blazor UI components by Radzen Ltd.</Description>
@@ -18,63 +18,54 @@
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<Title>Radzen Components for Blazor</Title>
<RepositoryUrl>https://github.com/radzenhq/radzen-blazor</RepositoryUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net5.0'">
<DefineConstants>NET5</DefineConstants>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibSassBuilder" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'netstandard2.1'" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net5.0'" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.2" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.12" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="" />
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
<None Include="icon.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LinkerConfig.xml">
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="LinkerConfig.xml">
<LogicalName>$(MSBuildProjectName).xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<UsingTask
TaskName="RemoveSourceMap"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<Task>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Using Namespace="System.Text"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
foreach (var file in Directory.EnumerateFiles("./wwwroot/css", "*.css"))
{
File.WriteAllText(file, File.ReadAllText(file).Replace("/*# sourceMappingURL=themes" + Path.DirectorySeparatorChar + Path.GetFileName(file) + ".map */", ""), Encoding.UTF8);
}
]]>
</Code>
</Task>
</UsingTask>
<Target Name="ToolRestore" BeforeTargets="PreBuildEvent">
<Exec Command="dotnet tool restore" StandardOutputImportance="high" />
<PropertyGroup>
<LibSassOutputStyle>expanded</LibSassOutputStyle>
<EnableDefaultSassItems>false</EnableDefaultSassItems>
</PropertyGroup>
<ItemGroup>
<Sass Include="$(MSBuildProjectDirectory)/themes/*.scss" Exclude="$(MSBuildProjectDirectory)/themes/_*.scss" Condition="'$(TargetFramework)' == 'net6.0'" />
</ItemGroup>
<Target Name="Sass" BeforeTargets="BeforeBuild" Condition="'$(TargetFramework)' == 'net6.0'">
<PropertyGroup>
<_SassFileList>@(Sass->'&quot;%(FullPath)&quot;', ' ')</_SassFileList>
<LibSassBuilderArgs>files $(_SassFileList) --outputstyle $(LibSassOutputStyle) --level $(LibSassOutputLevel)</LibSassBuilderArgs>
</PropertyGroup>
<Message Text="$(LibSassBuilderArgs)" Importance="$(LibSassMessageLevel)" />
<Message Text="Converted SassFile list to argument" Importance="$(LibSassMessageLevel)" />
</Target>
<Target Name="PreBuild" AfterTargets="ToolRestore">
<Exec Command="dotnet tool run webcompiler -r themes -o wwwroot/css -z disable -m disable -p disable" StandardOutputImportance="high" />
<Target Name="MoveCss" AfterTargets="AfterCompile" Condition="'$(TargetFramework)' == 'net6.0'" >
<ItemGroup>
<CssFiles Include="$(MSBuildProjectDirectory)\themes\*.css" />
<CssFile Include="$(MSBuildProjectDirectory)/themes/*.css" />
</ItemGroup>
<ItemGroup>
<BootstrapFiles Include="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap\**\*.*" />
</ItemGroup>
<Delete Files="@(CssFiles)" />
<Delete Files="@(BootstrapFiles)" />
<RemoveDir Directories="$(MSBuildProjectDirectory)\wwwroot\css\bootstrap" />
<RemoveSourceMap />
<Move SourceFiles="@(CssFile)" DestinationFolder="$(MSBuildProjectDirectory)/wwwroot/css/" />
</Target>
</Project>

View File

@@ -17,7 +17,7 @@
if (!item.Visible)
continue;
<div class="rz-accordion-header rz-state-active" @attributes="item.Attributes" style="@item.Style">
<div class="rz-accordion-header" @attributes="item.Attributes" style="@item.Style">
<a @onclick="@((args) => SelectItem(item))" href="javascript:void(0)" role="tab" tabindex="0"
id="@($"rz-accordiontab-{items.IndexOf(item)}")" aria-controls="@($"rz-accordiontab-{items.IndexOf(item)}-content")" aria-expanded="true">
@if (IsSelected(i, item))
@@ -49,112 +49,4 @@
}
}
</div>
}
@code {
protected override string GetComponentCssClass()
{
return "rz-accordion";
}
[Parameter]
public bool Multiple { get; set; }
[Parameter]
public int SelectedIndex { get; set; } = 0;
[Parameter]
public EventCallback<int> Expand { get; set; }
[Parameter]
public EventCallback<int> Collapse { get; set; }
[Parameter]
public RenderFragment Items { get; set; }
List<RadzenAccordionItem> items = new List<RadzenAccordionItem>();
public void AddItem(RadzenAccordionItem item)
{
if (items.IndexOf(item) == -1)
{
if (item.Selected)
{
SelectedIndex = items.Count;
if (!Multiple)
{
expandedIdexes.Clear();
}
if (!expandedIdexes.Contains(SelectedIndex))
{
expandedIdexes.Add(SelectedIndex);
}
}
items.Add(item);
StateHasChanged();
}
}
public void RemoveItem(RadzenAccordionItem item)
{
if (items.Contains(item))
{
items.Remove(item);
try { InvokeAsync(StateHasChanged); } catch { }
}
}
internal void Refresh()
{
StateHasChanged();
}
protected bool IsSelected(int index, RadzenAccordionItem item)
{
return expandedIdexes.Contains(index);
}
List<int> expandedIdexes = new List<int>();
internal async System.Threading.Tasks.Task SelectItem(RadzenAccordionItem item)
{
await CollapseAll(item);
var itemIndex = items.IndexOf(item);
if (!expandedIdexes.Contains(itemIndex))
{
expandedIdexes.Add(itemIndex);
await Expand.InvokeAsync(itemIndex);
}
else
{
expandedIdexes.Remove(itemIndex);
await Collapse.InvokeAsync(itemIndex);
}
if (!Multiple)
{
SelectedIndex = itemIndex;
}
StateHasChanged();
}
async System.Threading.Tasks.Task CollapseAll(RadzenAccordionItem item)
{
if (!Multiple && items.Count > 1)
{
foreach (var i in items.Where(i => i != item))
{
var itemIndex = items.IndexOf(i);
if (expandedIdexes.Contains(itemIndex))
{
expandedIdexes.Remove(itemIndex);
await Collapse.InvokeAsync(items.IndexOf(i));
}
}
}
}
}

View File

@@ -0,0 +1,173 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Linq;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenAccordion component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenAccordion&gt;
/// &lt;Items&gt;
/// &lt;RadzenAccordionItem Text="Orders" Icon="account_balance_wallet"&gt;
/// Details for Orders
/// &lt;/RadzenAccordionItem&gt;
/// &lt;RadzenAccordionItem Text="Employees" Icon="account_box"&gt;
/// Details for Employees
/// &lt;/RadzenAccordionItem&gt;
/// &lt;/Items&gt;
/// &lt;/RadzenAccordion&gt;
/// </code>
/// </example>
public partial class RadzenAccordion : RadzenComponent
{
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-accordion";
}
/// <summary>
/// Gets or sets a value indicating whether multiple items can be expanded.
/// </summary>
/// <value><c>true</c> if multiple items can be expanded; otherwise, <c>false</c>.</value>
[Parameter]
public bool Multiple { get; set; }
/// <summary>
/// Gets or sets the index of the selected item.
/// </summary>
/// <value>The index of the selected item.</value>
[Parameter]
public int SelectedIndex { get; set; } = 0;
/// <summary>
/// Gets or sets a callback raised when the item is expanded.
/// </summary>
/// <value>The expand.</value>
[Parameter]
public EventCallback<int> Expand { get; set; }
/// <summary>
/// Gets or sets a callback raised when the item is collapsed.
/// </summary>
/// <value>The collapse.</value>
[Parameter]
public EventCallback<int> Collapse { get; set; }
/// <summary>
/// Gets or sets the items.
/// </summary>
/// <value>The items.</value>
[Parameter]
public RenderFragment Items { get; set; }
List<RadzenAccordionItem> items = new List<RadzenAccordionItem>();
/// <summary>
/// Adds the item.
/// </summary>
/// <param name="item">The item.</param>
public void AddItem(RadzenAccordionItem item)
{
if (items.IndexOf(item) == -1)
{
if (item.Selected)
{
SelectedIndex = items.Count;
if (!Multiple)
{
expandedIdexes.Clear();
}
if (!expandedIdexes.Contains(SelectedIndex))
{
expandedIdexes.Add(SelectedIndex);
}
}
items.Add(item);
StateHasChanged();
}
}
/// <summary>
/// Removes the item.
/// </summary>
/// <param name="item">The item.</param>
public void RemoveItem(RadzenAccordionItem item)
{
if (items.Contains(item))
{
items.Remove(item);
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}
/// <summary>
/// Refreshes this instance.
/// </summary>
internal void Refresh()
{
StateHasChanged();
}
/// <summary>
/// Determines whether the specified index is selected.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if the specified index is selected; otherwise, <c>false</c>.</returns>
protected bool IsSelected(int index, RadzenAccordionItem item)
{
return expandedIdexes.Contains(index);
}
List<int> expandedIdexes = new List<int>();
internal async System.Threading.Tasks.Task SelectItem(RadzenAccordionItem item)
{
await CollapseAll(item);
var itemIndex = items.IndexOf(item);
if (!expandedIdexes.Contains(itemIndex))
{
expandedIdexes.Add(itemIndex);
await Expand.InvokeAsync(itemIndex);
}
else
{
expandedIdexes.Remove(itemIndex);
await Collapse.InvokeAsync(itemIndex);
}
if (!Multiple)
{
SelectedIndex = itemIndex;
}
StateHasChanged();
}
async System.Threading.Tasks.Task CollapseAll(RadzenAccordionItem item)
{
if (!Multiple && items.Count > 1)
{
foreach (var i in items.Where(i => i != item))
{
var itemIndex = items.IndexOf(i);
if (expandedIdexes.Contains(itemIndex))
{
expandedIdexes.Remove(itemIndex);
await Collapse.InvokeAsync(items.IndexOf(i));
}
}
}
}
}
}

View File

@@ -0,0 +1,113 @@
using Microsoft.AspNetCore.Components;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// Class RadzenAccordionItem.
/// </summary>
public partial class RadzenAccordionItem : RadzenComponent
{
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
[Parameter]
public string Text { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>The icon.</value>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenAccordionItem"/> is selected.
/// </summary>
/// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
[Parameter]
public bool Selected { get; set; }
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
bool _visible = true;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenAccordionItem"/> is visible.
/// </summary>
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
[Parameter]
public override bool Visible
{
get
{
return _visible;
}
set
{
if (_visible != value)
{
_visible = value;
if (Accordion != null)
{
Accordion.Refresh();
}
}
}
}
RadzenAccordion _accordion;
/// <summary>
/// Gets or sets the accordion.
/// </summary>
/// <value>The accordion.</value>
[CascadingParameter]
public RadzenAccordion Accordion
{
get
{
return _accordion;
}
set
{
if (_accordion != value)
{
_accordion = value;
_accordion.AddItem(this);
}
}
}
/// <summary>
/// Set parameters as an asynchronous operation.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>A Task representing the asynchronous operation.</returns>
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.DidParameterChange(nameof(Selected), Selected))
{
Accordion?.SelectItem(this);
}
await base.SetParametersAsync(parameters);
}
/// <summary>
/// Disposes this instance.
/// </summary>
public override void Dispose()
{
base.Dispose();
Accordion?.RemoveItem(this);
}
}
}

View File

@@ -1,68 +0,0 @@
@inherits RadzenComponent
@code {
[Parameter]
public string Text { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter]
public bool Selected { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
bool _visible = true;
[Parameter]
public override bool Visible
{
get
{
return _visible;
}
set
{
if (_visible != value)
{
_visible = value;
Accordion.Refresh();
}
}
}
RadzenAccordion _accordion;
[CascadingParameter]
public RadzenAccordion Accordion
{
get
{
return _accordion;
}
set
{
if (_accordion != value)
{
_accordion = value;
_accordion.AddItem(this);
}
}
}
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.DidParameterChange(nameof(Selected), Selected))
{
Accordion?.SelectItem(this);
}
await base.SetParametersAsync(parameters);
}
public override void Dispose()
{
base.Dispose();
Accordion?.RemoveItem(this);
}
}

View File

@@ -39,149 +39,3 @@
<CascadingValue Value=@this>
@ChildContent
</CascadingValue>
@code {
[CascadingParameter]
public RadzenArcGauge Gauge { get; set; }
[Parameter]
public string Stroke { get; set; }
[Parameter]
public double StrokeWidth { get; set; } = 1;
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public double TickLength { get; set; } = 10;
[Parameter]
public double MinorTickLength { get; set; } = 5;
[Parameter]
public double TickLabelOffset { get; set; } = 25;
[Parameter]
public string FormatString { get; set; }
[Parameter]
public string Fill { get; set; }
[Parameter]
public double Height { get; set; } = 0.2;
[Parameter]
public Func<double, string> Formatter { get; set; } = value => value.ToString();
[Parameter]
public double StartAngle { get; set; } = -90;
[Parameter]
public GaugeTickPosition TickPosition { get; set; } = GaugeTickPosition.None;
[Parameter]
public double EndAngle { get; set; } = 90;
[Parameter]
public double Radius { get; set; } = 1;
[Parameter]
public bool ShowFirstTick { get; set; } = true;
[Parameter]
public bool ShowLastTick { get; set; } = true;
[Parameter]
public bool ShowTickLabels { get; set; } = true;
[Parameter]
public double X { get; set; } = 0.5;
[Parameter]
public double Min { get; set; } = 0;
[Parameter]
public double Max { get; set; } = 100;
[Parameter]
public double Step { get; set; } = 20;
[Parameter]
public double MinorStep { get; set; }
[Parameter]
public double Y { get; set; } = 0.5;
[Parameter]
public double Margin { get; set; } = 16;
public double CurrentStrokeWidth
{
get
{
if (TickPosition == GaugeTickPosition.None)
{
return 0;
}
return StrokeWidth;
}
}
public double CurrentRadius
{
get
{
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
radius *= Radius;
if (TickPosition == GaugeTickPosition.Outside)
{
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
}
return radius;
}
}
double CurrentScaleRadius
{
get
{
if (TickPosition == GaugeTickPosition.Inside)
{
return CurrentRadius - CurrentSize;
}
return CurrentRadius;
}
}
public double CurrentSize
{
get
{
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
if (TickPosition == GaugeTickPosition.Outside)
{
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
}
return radius * Height;
}
}
public Point CurrentCenter
{
get
{
var x = X * Gauge.Width;
var y = Y * Gauge.Height;
return new Point { X = x.Value, Y = y.Value };
}
}
}

View File

@@ -0,0 +1,272 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenArcGaugeScale component.
/// </summary>
public partial class RadzenArcGaugeScale: ComponentBase
{
/// <summary>
/// Gets or sets the gauge.
/// </summary>
/// <value>The gauge.</value>
[CascadingParameter]
public RadzenArcGauge Gauge { get; set; }
/// <summary>
/// Gets or sets the stroke.
/// </summary>
/// <value>The stroke.</value>
[Parameter]
public string Stroke { get; set; }
/// <summary>
/// Gets or sets the width of the stroke.
/// </summary>
/// <value>The width of the stroke.</value>
[Parameter]
public double StrokeWidth { get; set; } = 1;
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the length of the tick.
/// </summary>
/// <value>The length of the tick.</value>
[Parameter]
public double TickLength { get; set; } = 10;
/// <summary>
/// Gets or sets the length of the minor tick.
/// </summary>
/// <value>The length of the minor tick.</value>
[Parameter]
public double MinorTickLength { get; set; } = 5;
/// <summary>
/// Gets or sets the tick label offset.
/// </summary>
/// <value>The tick label offset.</value>
[Parameter]
public double TickLabelOffset { get; set; } = 25;
/// <summary>
/// Gets or sets the format string.
/// </summary>
/// <value>The format string.</value>
[Parameter]
public string FormatString { get; set; }
/// <summary>
/// Gets or sets the fill.
/// </summary>
/// <value>The fill.</value>
[Parameter]
public string Fill { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
[Parameter]
public double Height { get; set; } = 0.2;
/// <summary>
/// Gets or sets the formatter.
/// </summary>
/// <value>The formatter.</value>
[Parameter]
public Func<double, string> Formatter { get; set; } = value => value.ToString();
/// <summary>
/// Gets or sets the start angle.
/// </summary>
/// <value>The start angle.</value>
[Parameter]
public double StartAngle { get; set; } = -90;
/// <summary>
/// Gets or sets the tick position.
/// </summary>
/// <value>The tick position.</value>
[Parameter]
public GaugeTickPosition TickPosition { get; set; } = GaugeTickPosition.None;
/// <summary>
/// Gets or sets the end angle.
/// </summary>
/// <value>The end angle.</value>
[Parameter]
public double EndAngle { get; set; } = 90;
/// <summary>
/// Gets or sets the radius.
/// </summary>
/// <value>The radius.</value>
[Parameter]
public double Radius { get; set; } = 1;
/// <summary>
/// Gets or sets a value indicating whether first tick is shown.
/// </summary>
/// <value><c>true</c> if first tick is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowFirstTick { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether last tick is shown.
/// </summary>
/// <value><c>true</c> if last tick is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowLastTick { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether to show tick labels.
/// </summary>
/// <value><c>true</c> if tick labels are shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowTickLabels { get; set; } = true;
/// <summary>
/// Gets or sets the x.
/// </summary>
/// <value>The x.</value>
[Parameter]
public double X { get; set; } = 0.5;
/// <summary>
/// Determines the minimum value.
/// </summary>
/// <value>The minimum value.</value>
[Parameter]
public double Min { get; set; } = 0;
/// <summary>
/// Determines the maximum value.
/// </summary>
/// <value>The maximum value.</value>
[Parameter]
public double Max { get; set; } = 100;
/// <summary>
/// Gets or sets the step.
/// </summary>
/// <value>The step.</value>
[Parameter]
public double Step { get; set; } = 20;
/// <summary>
/// Gets or sets the minor step.
/// </summary>
/// <value>The minor step.</value>
[Parameter]
public double MinorStep { get; set; }
/// <summary>
/// Gets or sets the y.
/// </summary>
/// <value>The y.</value>
[Parameter]
public double Y { get; set; } = 0.5;
/// <summary>
/// Gets or sets the margin.
/// </summary>
/// <value>The margin.</value>
[Parameter]
public double Margin { get; set; } = 16;
/// <summary>
/// Gets the width of the current stroke.
/// </summary>
/// <value>The width of the current stroke.</value>
public double CurrentStrokeWidth
{
get
{
if (TickPosition == GaugeTickPosition.None)
{
return 0;
}
return StrokeWidth;
}
}
/// <summary>
/// Gets the current radius.
/// </summary>
/// <value>The current radius.</value>
public double CurrentRadius
{
get
{
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
radius *= Radius;
if (TickPosition == GaugeTickPosition.Outside)
{
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
}
return radius;
}
}
double CurrentScaleRadius
{
get
{
if (TickPosition == GaugeTickPosition.Inside)
{
return CurrentRadius - CurrentSize;
}
return CurrentRadius;
}
}
/// <summary>
/// Gets the current size.
/// </summary>
/// <value>The current size.</value>
public double CurrentSize
{
get
{
var radius = Math.Min(Gauge.Width.Value, Gauge.Height.Value) / 2 - Margin * 2;
if (TickPosition == GaugeTickPosition.Outside)
{
radius -= TextMeasurer.TextWidth(Max.ToString(), 16);
}
return radius * Height;
}
}
/// <summary>
/// Gets the current center.
/// </summary>
/// <value>The current center.</value>
public Point CurrentCenter
{
get
{
var x = X * Gauge.Width;
var y = Y * Gauge.Height;
return new Point { X = x.Value, Y = y.Value };
}
}
}
}

View File

@@ -17,54 +17,3 @@
Size=@Scale.CurrentSize
/>
</g>
@code {
[Parameter]
public double Value { get; set; }
[CascadingParameter]
public RadzenArcGaugeScale Scale { get; set; }
[Parameter]
public string Stroke { get; set; }
[Parameter]
public double StrokeWidth { get; set; }
[Parameter]
public string Fill { get; set; }
[Parameter]
public bool ShowValue { get; set; } = true;
[Parameter]
public string FormatString { get; set; }
[Parameter]
public RenderFragment<RadzenArcGaugeScaleValue> Template { get; set; }
[CascadingParameter]
public RadzenArcGauge Gauge { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
Gauge.AddValue(this);
}
public override async Task SetParametersAsync(ParameterView parameters)
{
var shouldRefresh = false;
if (parameters.DidParameterChange(nameof(Value), Value) || parameters.DidParameterChange(nameof(ShowValue), ShowValue))
{
shouldRefresh = true;
}
await base.SetParametersAsync(parameters);
if (shouldRefresh)
{
Gauge.Reload();
}
}
}

View File

@@ -0,0 +1,99 @@
using Microsoft.AspNetCore.Components;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenArcGaugeScaleValue component.
/// </summary>
public partial class RadzenArcGaugeScaleValue : ComponentBase
{
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Parameter]
public double Value { get; set; }
/// <summary>
/// Gets or sets the scale.
/// </summary>
/// <value>The scale.</value>
[CascadingParameter]
public RadzenArcGaugeScale Scale { get; set; }
/// <summary>
/// Gets or sets the stroke.
/// </summary>
/// <value>The stroke.</value>
[Parameter]
public string Stroke { get; set; }
/// <summary>
/// Gets or sets the width of the stroke.
/// </summary>
/// <value>The width of the stroke.</value>
[Parameter]
public double StrokeWidth { get; set; }
/// <summary>
/// Gets or sets the fill.
/// </summary>
/// <value>The fill.</value>
[Parameter]
public string Fill { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to show value.
/// </summary>
/// <value><c>true</c> if value is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowValue { get; set; } = true;
/// <summary>
/// Gets or sets the format string.
/// </summary>
/// <value>The format string.</value>
[Parameter]
public string FormatString { get; set; }
/// <summary>
/// Gets or sets the template.
/// </summary>
/// <value>The template.</value>
[Parameter]
public RenderFragment<RadzenArcGaugeScaleValue> Template { get; set; }
/// <summary>
/// Gets or sets the gauge.
/// </summary>
/// <value>The gauge.</value>
[CascadingParameter]
public RadzenArcGauge Gauge { get; set; }
/// <inheritdoc />
protected override void OnInitialized()
{
base.OnInitialized();
Gauge.AddValue(this);
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
var shouldRefresh = false;
if (parameters.DidParameterChange(nameof(Value), Value) || parameters.DidParameterChange(nameof(ShowValue), ShowValue))
{
shouldRefresh = true;
}
await base.SetParametersAsync(parameters);
if (shouldRefresh)
{
Gauge.Reload();
}
}
}
}

View File

@@ -6,64 +6,6 @@
@ChildContent
</CascadingValue>
@code {
[Parameter]
public string Stroke { get; set; }
[Parameter]
public string Fill { get; set; }
[Parameter]
public double StrokeWidth { get; set; } = 2;
[Parameter]
public LineType LineType { get; set; }
[Parameter]
public bool Smooth { get; set; }
public override string Color
{
get
{
return Stroke;
}
}
public override bool Contains(double x, double y)
{
var tolerance = 25;
var category = ComposeCategory(Chart.CategoryScale);
var value = ComposeValue(Chart.ValueScale);
var points = Items.Select(item => new Point { X = category(item), Y = value(item) }).ToArray();
var valueTicks = Chart.ValueScale.Ticks(Chart.ValueAxis.TickDistance);
var axisY = Chart.ValueScale.Scale(Math.Max(0, valueTicks.Start));
if (points.Any())
{
for (var i = 0; i < points.Length - 1; i++)
{
var start = points[i];
var end = points[i + 1];
var polygon = new[] {
new Point { X = start.X, Y = start.Y - tolerance },
new Point { X = end.X, Y = end.Y - tolerance },
new Point { X = end.X, Y = axisY },
new Point { X = start.X, Y = axisY },
};
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
{
return true;
}
}
}
return false;
}
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
{
var category = ComposeCategory(categoryScale);

View File

@@ -0,0 +1,137 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Radzen.Blazor
{
/// <summary>
/// Renders area series in <see cref="RadzenChart" />.
/// </summary>
public partial class RadzenAreaSeries<TItem> : CartesianSeries<TItem>
{
/// <summary>
/// Specifies the color of the line.
/// </summary>
/// <value>The stroke.</value>
[Parameter]
public string Stroke { get; set; }
/// <summary>
/// Specifies the fill (background color) of the area series.
/// </summary>
/// <value>The fill.</value>
[Parameter]
public string Fill { get; set; }
/// <summary>
/// Gets or sets the pixel width of the line. Set to <c>2</c> by default.
/// </summary>
/// <value>The width of the stroke.</value>
[Parameter]
public double StrokeWidth { get; set; } = 2;
/// <summary>
/// Specifies the line type.
/// </summary>
[Parameter]
public LineType LineType { get; set; }
/// <summary>
/// Specifies whether to render a smooth line. Set to <c>false</c> by default.
/// </summary>
[Parameter]
public bool Smooth { get; set; }
/// <inheritdoc />
public override string Color
{
get
{
return Stroke;
}
}
/// <inheritdoc />
protected override string TooltipStyle(TItem item)
{
var style = base.TooltipStyle(item);
var index = Items.IndexOf(item);
if (index >= 0)
{
var color = Fill;
if (color != null)
{
style = $"{style}; border-color: {color};";
}
}
return style;
}
/// <inheritdoc />
public override bool Contains(double x, double y, double tolerance)
{
var category = ComposeCategory(Chart.CategoryScale);
var value = ComposeValue(Chart.ValueScale);
var points = Items.Select(item => new Point { X = category(item), Y = value(item) }).ToArray();
var valueTicks = Chart.ValueScale.Ticks(Chart.ValueAxis.TickDistance);
var axisY = Chart.ValueScale.Scale(Math.Max(0, valueTicks.Start));
if (points.Length > 0)
{
if (points.Length == 1)
{
var point = points[0];
var polygon = new[] {
new Point { X = point.X - tolerance, Y = point.Y - tolerance },
new Point { X = point.X - tolerance, Y = point.Y + tolerance },
new Point { X = point.X + tolerance, Y = point.Y + tolerance },
new Point { X = point.X + tolerance, Y = point.Y - tolerance },
};
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
{
return true;
}
}
else
{
for (var i = 0; i < points.Length - 1; i++)
{
var start = points[i];
var end = points[i + 1];
var polygon = new[]
{
new Point { X = start.X, Y = start.Y - tolerance },
new Point { X = end.X, Y = end.Y - tolerance },
new Point { X = end.X, Y = axisY },
new Point { X = start.X, Y = axisY },
};
if (InsidePolygon(new Point { X = x, Y = y }, polygon))
{
return true;
}
}
}
}
return false;
}
/// <inheritdoc />
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
{
return base.GetDataLabels(offsetX, offsetY - 16);
}
}
}

View File

@@ -1,4 +1,5 @@
@using Radzen
@using Radzen.Blazor.Rendering
@using System.Collections
@using System.Linq.Dynamic.Core
@using Microsoft.AspNetCore.Components.Forms
@@ -9,19 +10,18 @@
@if (Visible)
{
<div @ref="@Element" style="@($"{Style};display:inline-block;")" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
<span class="rz-autocomplete" style="width:100%">
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
onfocus="@OpenScript()" onkeypress="@OpenScript()" tabindex="@TabIndex" @onchange="@OnChange"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
class="@getCssClasses()"
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
</span><div id="@PopupID" class="rz-autocomplete-panel" style="display:none; transform: none; box-sizing: border-box; max-height: 200px;">
<input @ref="@search" @onkeydown="@OnFilterKeyPress" value="@Value" disabled="@Disabled"
onkeypress="@OpenScript()" tabindex="@TabIndex" @onchange="@OnChange"
aria-autocomplete="list" aria-haspopup="true" autocomplete="off" role="combobox"
class="@InputClassList"
type="text" id="@Name" aria-expanded="true" placeholder="@Placeholder" />
<div id="@PopupID" class="rz-autocomplete-panel" style="display:none; transform: none; box-sizing: border-box; max-height: 200px;">
<ul @ref="@list" class="rz-autocomplete-items rz-autocomplete-list" role="listbox">
@if (!string.IsNullOrEmpty(searchText) || !string.IsNullOrEmpty(customSearchText))
{
@foreach (var item in LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>()))
{
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))">
<li role="option" class="rz-autocomplete-list-item" @onclick="@(() => OnSelectItem(item))" onmousedown="Radzen.activeElement = null">
<span>@PropertyAccess.GetItemOrValueFromProperty(item, TextProperty)</span>
</li>
}
@@ -30,197 +30,3 @@
</div>
</div>
}
@code {
[Parameter]
public int MinLength { get; set; } = 1;
[Parameter]
public int FilterDelay { get; set; } = 500;
protected ElementReference search;
protected ElementReference list;
string customSearchText;
int selectedIndex = -1;
protected async Task OnFilterKeyPress(KeyboardEventArgs args)
{
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>())).OfType<object>();
var key = args.Code != null ? args.Code : args.Key;
if (key == "ArrowDown" || key == "ArrowUp")
{
try
{
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", selectedIndex);
}
catch (Exception)
{
//
}
}
else if (key == "Enter")
{
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
{
await OnSelectItem(items.ElementAt(selectedIndex));
selectedIndex = -1;
}
}
else if (key == "Escape")
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
else if(key != "Tab")
{
selectedIndex = -1;
Debounce(DebounceFilter, FilterDelay);
}
}
async Task DebounceFilter()
{
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
if (value.Length < MinLength)
return;
if (!LoadData.HasDelegate)
{
searchText = value;
await InvokeAsync(() => { StateHasChanged(); });
}
else
{
customSearchText = value;
await InvokeAsync(() => { LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Filter = customSearchText }); });
}
}
private string PopupID
{
get
{
return $"popup{UniqueID}";
}
}
private async Task OnSelectItem(object item)
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
await SelectItem(item);
}
protected override IQueryable Query
{
get
{
return Data != null && !string.IsNullOrEmpty(searchText) ? Data.AsQueryable() : null;
}
}
protected override IEnumerable View
{
get
{
if (Query != null)
{
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
return Query.Where($"{TextProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
}
return null;
}
}
protected async System.Threading.Tasks.Task OnChange(ChangeEventArgs args)
{
Value = args.Value;
await ValueChanged.InvokeAsync($"{Value}");
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
}
async System.Threading.Tasks.Task SelectItem(object item)
{
if (!string.IsNullOrEmpty(TextProperty))
{
Value = PropertyAccess.GetItemOrValueFromProperty(item, TextProperty);
}
else
{
Value = item;
}
await ValueChanged.InvokeAsync($"{Value}");
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
StateHasChanged();
}
private string getCssClasses()
{
return $"rz-inputtext rz-autocomplete-input{(Disabled ? " rz-state-disabled" : "")}";
}
private string OpenScript()
{
if (Disabled)
{
return string.Empty;
}
return $"Radzen.openPopup(this.parentNode, '{PopupID}', true)";
}
protected override string GetComponentCssClass()
{
var fieldCssClass = FieldIdentifier.FieldName != null ? EditContext?.FieldCssClass(FieldIdentifier) : "";
return $"{base.GetComponentCssClass()} {fieldCssClass}";
}
public override void Dispose()
{
base.Dispose();
if (IsJSRuntimeAvailable)
{
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
}
}
private bool firstRender = true;
protected override Task OnAfterRenderAsync(bool firstRender)
{
this.firstRender = firstRender;
return base.OnAfterRenderAsync(firstRender);
}
public override async Task SetParametersAsync(ParameterView parameters)
{
var shouldClose = false;
if (parameters.DidParameterChange(nameof(Visible), Visible))
{
var visible = parameters.GetValueOrDefault<bool>(nameof(Visible));
shouldClose = !visible;
}
await base.SetParametersAsync(parameters);
if (shouldClose && !firstRender)
{
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
}
}
}

View File

@@ -0,0 +1,253 @@
using Radzen;
using Radzen.Blazor.Rendering;
using System.Collections;
using System.Linq.Dynamic.Core;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System.Linq;
using System;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenAutoComplete component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenAutoComplete Data=@customers TextProperty="CompanyName" Change=@(args => Console.WriteLine($"Selected text: {args}")) /&gt;
/// </code>
/// </example>
public partial class RadzenAutoComplete : DataBoundFormComponent<string>
{
/// <summary>
/// Gets or sets the minimum length.
/// </summary>
/// <value>The minimum length.</value>
[Parameter]
public int MinLength { get; set; } = 1;
/// <summary>
/// Gets or sets the filter delay.
/// </summary>
/// <value>The filter delay.</value>
[Parameter]
public int FilterDelay { get; set; } = 500;
/// <summary>
/// Gets search input reference.
/// </summary>
protected ElementReference search;
/// <summary>
/// Gets list element reference.
/// </summary>
protected ElementReference list;
string customSearchText;
int selectedIndex = -1;
/// <summary>
/// Handles the <see cref="E:FilterKeyPress" /> event.
/// </summary>
/// <param name="args">The <see cref="KeyboardEventArgs"/> instance containing the event data.</param>
protected async Task OnFilterKeyPress(KeyboardEventArgs args)
{
var items = (LoadData.HasDelegate ? Data != null ? Data : Enumerable.Empty<object>() : (View != null ? View : Enumerable.Empty<object>())).OfType<object>();
var key = args.Code != null ? args.Code : args.Key;
if (key == "ArrowDown" || key == "ArrowUp")
{
try
{
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown", selectedIndex);
}
catch (Exception)
{
//
}
}
else if (key == "Enter")
{
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
{
await OnSelectItem(items.ElementAt(selectedIndex));
selectedIndex = -1;
}
}
else if (key == "Escape" || key == "Tab")
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
}
else
{
selectedIndex = -1;
Debounce(DebounceFilter, FilterDelay);
}
}
async Task DebounceFilter()
{
var value = await JSRuntime.InvokeAsync<string>("Radzen.getInputValue", search);
if (value.Length < MinLength)
return;
if (!LoadData.HasDelegate)
{
searchText = value;
await InvokeAsync(() => { StateHasChanged(); });
}
else
{
customSearchText = value;
await InvokeAsync(() => { LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Filter = customSearchText }); });
}
}
private string PopupID
{
get
{
return $"popup{UniqueID}";
}
}
private async Task OnSelectItem(object item)
{
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
await SelectItem(item);
}
/// <summary>
/// Gets the IQueryable.
/// </summary>
/// <value>The IQueryable.</value>
protected override IQueryable Query
{
get
{
return Data != null && !string.IsNullOrEmpty(searchText) ? Data.AsQueryable() : null;
}
}
/// <summary>
/// Gets the view - the Query with filtering applied.
/// </summary>
/// <value>The view.</value>
protected override IEnumerable View
{
get
{
if (Query != null)
{
string filterCaseSensitivityOperator = FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? ".ToLower()" : "";
return Query.Where($"{TextProperty}{filterCaseSensitivityOperator}.{Enum.GetName(typeof(StringFilterOperator), FilterOperator)}(@0)",
FilterCaseSensitivity == FilterCaseSensitivity.CaseInsensitive ? searchText.ToLower() : searchText);
}
return null;
}
}
/// <summary>
/// Handles the <see cref="E:Change" /> event.
/// </summary>
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
protected async System.Threading.Tasks.Task OnChange(ChangeEventArgs args)
{
Value = args.Value;
await ValueChanged.InvokeAsync($"{Value}");
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
}
async System.Threading.Tasks.Task SelectItem(object item)
{
if (!string.IsNullOrEmpty(TextProperty))
{
Value = PropertyAccess.GetItemOrValueFromProperty(item, TextProperty);
}
else
{
Value = item;
}
await ValueChanged.InvokeAsync($"{Value}");
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
StateHasChanged();
}
ClassList InputClassList => ClassList.Create("rz-inputtext rz-autocomplete-input")
.AddDisabled(Disabled);
private string OpenScript()
{
if (Disabled)
{
return string.Empty;
}
return $"Radzen.openPopup(this.parentNode, '{PopupID}', true)";
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("rz-autocomplete").ToString();
}
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
if (IsJSRuntimeAvailable)
{
JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
}
}
private bool firstRender = true;
/// <summary>
/// Called on after render asynchronous.
/// </summary>
/// <param name="firstRender">if set to <c>true</c> is first render.</param>
/// <returns>Task.</returns>
protected override Task OnAfterRenderAsync(bool firstRender)
{
this.firstRender = firstRender;
return base.OnAfterRenderAsync(firstRender);
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
var shouldClose = false;
if (parameters.DidParameterChange(nameof(Visible), Visible))
{
var visible = parameters.GetValueOrDefault<bool>(nameof(Visible));
shouldClose = !visible;
}
await base.SetParametersAsync(parameters);
if (shouldClose && !firstRender)
{
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
}
}
}
}

View File

@@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Represents the title configuration of a <see cref="AxisBase" />.
/// </summary>
public class RadzenAxisTitle : RadzenChartComponentBase
{
/// <summary>
/// Gets or sets the text displayed by the title.
/// </summary>
/// <value>The text.</value>
[Parameter]
public string Text { get; set; }
/// <summary>
/// Sets the axis with this configuration applies to.
/// </summary>
/// <value>The axis.</value>
[CascadingParameter]
public AxisBase Axis
{
set
{
value.Title = this;
}
}
internal double Size
{
get
{
return 16 * 0.875;
}
}
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Text), Text);
}
}
}

View File

@@ -1,28 +0,0 @@
@inherits RadzenChartComponentBase
@code {
[Parameter]
public string Text { get; set; }
[CascadingParameter]
public AxisBase Axis
{
set
{
value.Title = this;
}
}
internal double Size
{
get
{
return 16 * 0.875;
}
}
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Text), Text);
}
}

View File

@@ -0,0 +1,14 @@
@inherits RadzenComponent
@if (Visible)
{
<span @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
@if (ChildContent != null)
{
@ChildContent
}
else
{
@Text
}
</span>
}

View File

@@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenBadge component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenBadge BadgeStyle="BadgeStyle.Primary" Text="Primary" /&gt;
/// </code>
/// </example>
public partial class RadzenBadge : RadzenComponent
{
/// <inheritdoc />
protected override string GetComponentCssClass()
{
var classList = new List<string>();
classList.Add("rz-badge");
classList.Add($"rz-badge-{BadgeStyle.ToString().ToLowerInvariant()}");
if (IsPill)
{
classList.Add("rz-badge-pill");
}
return string.Join(" ", classList);
}
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
[Parameter]
public string Text { get; set; }
/// <summary>
/// Gets or sets the badge style.
/// </summary>
/// <value>The badge style.</value>
[Parameter]
public BadgeStyle BadgeStyle { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is pill.
/// </summary>
/// <value><c>true</c> if this instance is pill; otherwise, <c>false</c>.</value>
[Parameter]
public bool IsPill { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Common configuration of <see cref="RadzenBarSeries{TItem}" />.
/// </summary>
public partial class RadzenBarOptions : RadzenChartComponentBase
{
/// <summary>
/// Gets or sets the border radius of the bars.
/// </summary>
/// <value>The radius. Values greater than <c>0</c> make rounded corners.</value>
[Parameter]
public double Radius { get; set; }
/// <summary>
/// Gets or sets the margin between bars.
/// </summary>
/// <value>The margin. By default set to <c>10</c></value>
[Parameter]
public double Margin { get; set; } = 10;
/// <inheritdoc />
protected override void Initialize()
{
Chart.BarOptions = this;
}
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
}
}
}

View File

@@ -1,18 +0,0 @@
@inherits RadzenChartComponentBase
@code {
[Parameter]
public double Radius { get; set; }
[Parameter]
public double Margin { get; set; } = 10;
protected override void Initialize()
{
Chart.BarOptions = this;
}
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
}
}

View File

@@ -10,142 +10,6 @@
</CascadingValue>
@code {
[Parameter]
public string Fill { get; set; }
[Parameter]
public IEnumerable<string> Fills { get; set; }
[Parameter]
public string Stroke { get; set; }
[Parameter]
public IEnumerable<string> Strokes { get; set; }
[Parameter]
public double StrokeWidth { get; set; }
[Parameter]
public LineType LineType { get; set; }
public override string Color
{
get
{
return Fill;
}
}
public override ScaleBase TransformCategoryScale(ScaleBase scale)
{
return base.TransformValueScale(scale);
}
public override ScaleBase TransformValueScale(ScaleBase scale)
{
return base.TransformCategoryScale(scale);
}
private IList<IChartSeries> BarSeries
{
get
{
return Chart.Series.Where(series => series is IChartBarSeries).Cast<IChartSeries>().ToList();
}
}
private IList<IChartSeries> VisibleBarSeries
{
get
{
return BarSeries.Where(series => series.Visible).ToList();
}
}
private double BandHeight
{
get
{
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
var bands = VisibleBarSeries.Cast<IChartBarSeries>().Max(series => series.Count) + 2;
return availableHeight / bands;
}
}
int IChartBarSeries.Count
{
get
{
return Items.Count;
}
}
public override bool Contains(double x, double y)
{
return DataAt(x, y) != null;
}
protected override double TooltipX(TItem item)
{
var value = Chart.CategoryScale.Compose(Value);
var x = value(item);
return x;
}
protected override string TooltipValue(TItem item)
{
return Chart.ValueAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(Value(item)));
}
protected override string TooltipTitle(TItem item)
{
var category = Category(Chart.ValueScale);
return Chart.CategoryAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(category(item)));
}
public override object DataAt(double x, double y)
{
var value = ComposeValue(Chart.CategoryScale);
var category = ComposeCategory(Chart.ValueScale);
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
var x0 = Chart.CategoryScale.Scale(Math.Max(0, ticks.Start));
var barSeries = VisibleBarSeries;
var index = barSeries.IndexOf(this);
var padding = Chart.BarOptions.Margin;
var bandHeight = BandHeight;
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
foreach(var data in Items)
{
var startY = category(data) - bandHeight / 2 + index * height + index * padding;
var endY = startY + height;
var dataX = value(data);
var startX = Math.Min(dataX, x0);
var endX = Math.Max(dataX, x0);
if (startX <= x && x <= endX && startY <= y && y <= endY)
{
return data;
}
}
return null;
}
protected override double TooltipY(TItem item)
{
var category = ComposeCategory(Chart.ValueScale);
var barSeries = VisibleBarSeries;
var index = barSeries.IndexOf(this);
var padding = Chart.BarOptions.Margin;
var bandHeight = BandHeight;
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
var y = category(item) - bandHeight / 2 + index * height + index * padding;
return y + height / 2;
}
public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
{
var value = ComposeValue(categoryScale);

View File

@@ -0,0 +1,229 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Radzen.Blazor
{
/// <summary>
/// Renders bar series in <see cref="RadzenChart" />.
/// </summary>
/// <typeparam name="TItem">The type of the series data item.</typeparam>
public partial class RadzenBarSeries<TItem> : CartesianSeries<TItem>, IChartBarSeries
{
/// <summary>
/// Specifies the fill (background color) of the bar series.
/// </summary>
/// <value>The fill.</value>
[Parameter]
public string Fill { get; set; }
/// <summary>
/// Specifies a list of colors that will be used to set the individual bar backgrounds.
/// </summary>
/// <value>The fills.</value>
[Parameter]
public IEnumerable<string> Fills { get; set; }
/// <summary>
/// Specifies the stroke (border color) of the bar series.
/// </summary>
/// <value>The stroke.</value>
[Parameter]
public string Stroke { get; set; }
/// <summary>
/// Specifies a list of colors that will be used to set the individual bar borders.
/// </summary>
/// <value>The strokes.</value>
[Parameter]
public IEnumerable<string> Strokes { get; set; }
/// <summary>
/// Gets or sets the width of the stroke (border).
/// </summary>
/// <value>The width of the stroke.</value>
[Parameter]
public double StrokeWidth { get; set; }
/// <summary>
/// Gets or sets the type of the line used to render the bar border.
/// </summary>
/// <value>The type of the line.</value>
[Parameter]
public LineType LineType { get; set; }
/// <inheritdoc />
public override string Color
{
get
{
return Fill;
}
}
/// <inheritdoc />
public override ScaleBase TransformCategoryScale(ScaleBase scale)
{
return base.TransformValueScale(scale);
}
/// <inheritdoc />
public override ScaleBase TransformValueScale(ScaleBase scale)
{
return base.TransformCategoryScale(scale);
}
/// <inheritdoc />
protected override IList<object> GetCategories()
{
return base.GetCategories().Reverse().ToList();
}
private IList<IChartSeries> BarSeries
{
get
{
return Chart.Series.Where(series => series is IChartBarSeries).Cast<IChartSeries>().ToList();
}
}
private IList<IChartSeries> VisibleBarSeries
{
get
{
return BarSeries.Where(series => series.Visible).ToList();
}
}
/// <inheritdoc />
protected override string TooltipStyle(TItem item)
{
var style = base.TooltipStyle(item);
var index = Items.IndexOf(item);
if (index >= 0)
{
var color = PickColor(index, Fills, Fill);
if (color != null)
{
style = $"{style}; border-color: {color};";
}
}
return style;
}
private double BandHeight
{
get
{
var availableHeight = Chart.ValueScale.OutputSize; // - (Chart.ValueAxis.Padding * 2);
var bands = VisibleBarSeries.Cast<IChartBarSeries>().Max(series => series.Count) + 2;
return availableHeight / bands;
}
}
int IChartBarSeries.Count
{
get
{
return Items.Count;
}
}
/// <inheritdoc />
public override bool Contains(double x, double y, double tolerance)
{
return DataAt(x, y) != null;
}
/// <inheritdoc />
internal override double TooltipX(TItem item)
{
var value = Chart.CategoryScale.Compose(Value);
var x = value(item);
return x;
}
/// <inheritdoc />
protected override string TooltipValue(TItem item)
{
return Chart.ValueAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(Value(item)));
}
/// <inheritdoc />
protected override string TooltipTitle(TItem item)
{
var category = Category(Chart.ValueScale);
return Chart.CategoryAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(category(item)));
}
/// <inheritdoc />
public override object DataAt(double x, double y)
{
var value = ComposeValue(Chart.CategoryScale);
var category = ComposeCategory(Chart.ValueScale);
var ticks = Chart.CategoryScale.Ticks(Chart.ValueAxis.TickDistance);
var x0 = Chart.CategoryScale.Scale(Math.Max(0, ticks.Start));
var barSeries = VisibleBarSeries;
var index = barSeries.IndexOf(this);
var padding = Chart.BarOptions.Margin;
var bandHeight = BandHeight;
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
foreach (var data in Items)
{
var startY = category(data) - bandHeight / 2 + index * height + index * padding;
var endY = startY + height;
var dataX = value(data);
var startX = Math.Min(dataX, x0);
var endX = Math.Max(dataX, x0);
if (startX <= x && x <= endX && startY <= y && y <= endY)
{
return data;
}
}
return null;
}
/// <inheritdoc />
internal override double TooltipY(TItem item)
{
var category = ComposeCategory(Chart.ValueScale);
var barSeries = VisibleBarSeries;
var index = barSeries.IndexOf(this);
var padding = Chart.BarOptions.Margin;
var bandHeight = BandHeight;
var height = bandHeight / barSeries.Count() - padding + padding / barSeries.Count();
var y = category(item) - bandHeight / 2 + index * height + index * padding;
return y + height / 2;
}
/// <inheritdoc />
public override IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
{
var list = new List<ChartDataLabel>();
foreach (var d in Data)
{
list.Add(new ChartDataLabel
{
Position = new Point() { X = TooltipX(d) + offsetX + 8, Y = TooltipY(d) + offsetY },
TextAnchor = "start",
Text = Chart.ValueAxis.Format(Chart.CategoryScale, Value(d))
});
}
return list;
}
}
}

View File

@@ -6,41 +6,3 @@
@ChildContent
</div>
}
@code {
[Parameter]
public override string Style { get; set; } = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
protected override string GetComponentCssClass()
{
return "body";
}
public void Toggle()
{
Expanded = !Expanded;
StateHasChanged();
}
protected string GetStyle()
{
var marginLeft = 250;
if (!string.IsNullOrEmpty(Style))
{
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
{
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
}
}
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
}
[Parameter]
public bool Expanded { get; set; } = false;
[Parameter]
public EventCallback<bool> ExpandedChanged { get; set; }
}

View File

@@ -0,0 +1,126 @@
using Microsoft.AspNetCore.Components;
using System.Linq;
using Radzen.Blazor.Rendering;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.JSInterop;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenBody component.
/// </summary>
public partial class RadzenBody : RadzenComponentWithChildren
{
private const string DefaultStyle = "margin-top: 51px; margin-bottom: 57px; margin-left:250px;";
/// <summary>
/// Gets or sets the style.
/// </summary>
/// <value>The style.</value>
[Parameter]
public override string Style { get; set; } = DefaultStyle;
/// <inheritdoc />
protected override string GetComponentCssClass()
{
var classList = ClassList.Create("rz-body")
.Add("body")
.Add("body-expanded", Expanded);
return classList.ToString();
}
/// <summary>
/// Toggles this instance width and left margin.
/// </summary>
public void Toggle()
{
Expanded = !Expanded;
StateHasChanged();
}
/// <summary>
/// The <see cref="RadzenLayout" /> this component is nested in.
/// </summary>
[CascadingParameter]
public RadzenLayout Layout { get; set; }
/// <summary>
/// Gets the style.
/// </summary>
/// <returns>System.String.</returns>
protected string GetStyle()
{
if (Layout == null)
{
var marginLeft = 250;
var style = Style;
if (!string.IsNullOrEmpty(Style))
{
var marginLeftStyle = Style.Split(';').Where(i => i.Split(':')[0].Contains("margin-left")).FirstOrDefault();
if (!string.IsNullOrEmpty(marginLeftStyle) && marginLeftStyle.Contains("px"))
{
marginLeft = int.Parse(marginLeftStyle.Split(':')[1].Trim().Replace("px", "").Split('.')[0].Trim());
}
}
return $"{Style}; margin-left: {(Expanded ? 0 : marginLeft)}px";
}
else
{
var style = Style;
if (!string.IsNullOrEmpty(style))
{
style = style.Replace(DefaultStyle, "");
}
return $"{style}";
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenBody"/> is expanded.
/// </summary>
/// <value><c>true</c> if expanded; otherwise, <c>false</c>.</value>
[Parameter]
public bool Expanded { get; set; } = false;
/// <summary>
/// Gets or sets a callback raised when the component is expanded or collapsed.
/// </summary>
/// <value>The expanded changed callback.</value>
[Parameter]
public EventCallback<bool> ExpandedChanged { get; set; }
[Inject]
NavigationManager NavigationManager { get; set; }
/// <inheritdoc />
protected override Task OnInitializedAsync()
{
NavigationManager.LocationChanged += OnLocationChanged;
return base.OnInitializedAsync();
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
if (IsJSRuntimeAvailable && Layout != null)
{
JSRuntime.InvokeVoidAsync("eval", $"document.getElementById('{GetId()}').scrollTop = 0");
}
}
/// <inheritdoc />
public override void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
base.Dispose();
}
}
}

View File

@@ -0,0 +1,13 @@
@inherits RadzenComponentWithChildren
<CascadingValue Value="@Template">
@if (Visible)
{
<div class="@GetCssClass()" style="@Style" @attributes="@Attributes" id="@GetId()">
@if (ChildContent != null)
{
@ChildContent
}
</div>
}
</CascadingValue>

View File

@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// A component to display a Bread Crumb style menu
/// </summary>
public partial class RadzenBreadCrumb : RadzenComponentWithChildren
{
/// <summary>
/// An optional RenderFragment that is rendered per Item
/// </summary>
[Parameter]
public RenderFragment<RadzenBreadCrumbItem> Template { get; set; }
/// <inheritdoc/>
protected override string GetComponentCssClass()
{
return "rz-breadcrumb";
}
}
}

View File

@@ -0,0 +1,30 @@
@inherits RadzenComponent
@if (Visible)
{
<div class="@GetCssClass()" id="@GetId()" style="@Style" @attributes="@Attributes">
@if (ChildContent != null)
{
@ChildContent
}
else if (Template != null)
{
@Template(this)
}
else
{
@if (!string.IsNullOrWhiteSpace(Path))
{
<RadzenLink Icon="@Icon" Path="@Path" Text="@Text" />
}
else
{
@if (!string.IsNullOrWhiteSpace(Icon))
{
<RadzenIcon Icon="@Icon" />
}
<RadzenLabel Text="@Text" />
}
}
</div>
}

View File

@@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Bread Crumb Item Component
/// </summary>
public partial class RadzenBreadCrumbItem : RadzenComponent
{
/// <summary>
/// Cascaded Template Parameter from <see cref="RadzenBreadCrumb"/> Component
/// </summary>
[CascadingParameter]
public RenderFragment<RadzenBreadCrumbItem> Template { get; set; }
/// <summary>
/// The Displayed Text
/// </summary>
[Parameter]
public string Text { get; set; }
/// <summary>
/// An optional Link to be rendendered
/// </summary>
[Parameter]
public string Path { get; set; }
/// <summary>
/// An optional Icon to be rendered
/// </summary>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Template Parameter used only for this Item
/// Note: this overrides the <see cref="Template"/> Cascading Parameter
/// </summary>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <inheritdoc/>
protected override string GetComponentCssClass()
{
return "rz-breadcrumb-item";
}
}
}

View File

@@ -5,7 +5,7 @@
<button @ref="@Element" style="@Style" disabled="@IsDisabled"
type="@Enum.GetName(typeof(ButtonType), ButtonType).ToLower()"
@attributes="Attributes" class="@GetCssClass()" id="@GetId()"
@onclick="@((args) => OnClick(args))">
@onclick="@OnClick">
@if (ChildContent != null)
{
@ChildContent
@@ -38,69 +38,3 @@
}
</button>
}
@code {
private string getButtonSize()
{
return Size == ButtonSize.Medium ? "md" : "sm";
}
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string Text { get; set; } = "";
[Parameter]
public string Icon { get; set; }
[Parameter]
public string Image { get; set; }
[Parameter]
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
[Parameter]
public ButtonType ButtonType { get; set; } = ButtonType.Button;
[Parameter]
public ButtonSize Size { get; set; } = ButtonSize.Medium;
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> Click { get; set; }
[Parameter]
public bool IsBusy { get; set; }
[Parameter]
public string BusyText { get; set; } = "";
public bool IsDisabled { get => Disabled || IsBusy; }
bool clicking;
public async Task OnClick(MouseEventArgs args)
{
if (clicking)
{
return;
}
try
{
clicking = true;
await Click.InvokeAsync(args);
}
finally
{
clicking = false;
}
}
protected override string GetComponentCssClass()
{
return $"rz-button rz-button-{getButtonSize()} btn-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLower()}{(IsDisabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
}
}

View File

@@ -0,0 +1,137 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenButton component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenButton Click=@(args => Console.WriteLine("Button clicked")) Text="Button" /&gt;
/// </code>
/// </example>
public partial class RadzenButton : RadzenComponent
{
private string getButtonSize()
{
return Size == ButtonSize.Medium ? "md" : "sm";
}
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
[Parameter]
public string Text { get; set; } = "";
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>The icon.</value>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Gets or sets the image.
/// </summary>
/// <value>The image.</value>
[Parameter]
public string Image { get; set; }
/// <summary>
/// Gets or sets the button style.
/// </summary>
/// <value>The button style.</value>
[Parameter]
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
/// <summary>
/// Gets or sets the type of the button.
/// </summary>
/// <value>The type of the button.</value>
[Parameter]
public ButtonType ButtonType { get; set; } = ButtonType.Button;
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>The size.</value>
[Parameter]
public ButtonSize Size { get; set; } = ButtonSize.Medium;
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenButton"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public bool Disabled { get; set; }
/// <summary>
/// Gets or sets the click callback.
/// </summary>
/// <value>The click callback.</value>
[Parameter]
public EventCallback<MouseEventArgs> Click { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance busy text is shown.
/// </summary>
/// <value><c>true</c> if this instance busy text is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool IsBusy { get; set; }
/// <summary>
/// Gets or sets the busy text.
/// </summary>
/// <value>The busy text.</value>
[Parameter]
public string BusyText { get; set; } = "";
/// <summary>
/// Gets a value indicating whether this instance is disabled.
/// </summary>
/// <value><c>true</c> if this instance is disabled; otherwise, <c>false</c>.</value>
public bool IsDisabled { get => Disabled || IsBusy; }
bool clicking;
/// <summary>
/// Handles the <see cref="E:Click" /> event.
/// </summary>
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
public async Task OnClick(MouseEventArgs args)
{
if (clicking)
{
return;
}
try
{
clicking = true;
await Click.InvokeAsync(args);
}
finally
{
clicking = false;
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return $"rz-button rz-button-{getButtonSize()} btn-{Enum.GetName(typeof(ButtonStyle), ButtonStyle).ToLowerInvariant()}{(IsDisabled ? " rz-state-disabled" : "")}{(string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Icon) ? " rz-button-icon-only" : "")}";
}
}
}

View File

@@ -4,10 +4,3 @@
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@Style" id="@GetId()">@ChildContent</div>
}
@code {
protected override string GetComponentCssClass()
{
return "rz-card card";
}
}

View File

@@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using System;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenCard component.
/// </summary>
public partial class RadzenCard : RadzenComponentWithChildren
{
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return "rz-card card";
}
}
}

View File

@@ -26,6 +26,7 @@
@if (series.Visible)
{
@series.Render(CategoryScale, ValueScale);
@series.RenderOverlays(CategoryScale, ValueScale);
}
}
</g>
@@ -45,398 +46,3 @@
}
</div>
}
@code {
[Parameter]
public ColorScheme ColorScheme { get; set; }
double? Width { get; set; }
double? Height { get; set; }
double MarginTop { get; set; }
double MarginLeft { get; set; }
double MarginRight { get; set; }
double MarginBottom { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
internal ScaleBase CategoryScale { get; set; } = new LinearScale();
internal ScaleBase ValueScale { get; set; } = new LinearScale();
internal IList<IChartSeries> Series { get; set; } = new List<IChartSeries>();
internal RadzenColumnOptions ColumnOptions { get; set; } = new RadzenColumnOptions();
internal RadzenBarOptions BarOptions { get; set; } = new RadzenBarOptions();
internal RadzenLegend Legend { get; set; } = new RadzenLegend();
internal RadzenCategoryAxis CategoryAxis { get; set; } = new RadzenCategoryAxis();
internal RadzenValueAxis ValueAxis { get; set; } = new RadzenValueAxis();
internal RadzenChartTooltipOptions Tooltip { get; set; } = new RadzenChartTooltipOptions();
internal void AddSeries(IChartSeries series)
{
if (!Series.Contains(series))
{
Series.Add(series);
}
}
internal void RemoveSeries(IChartSeries series)
{
Series.Remove(series);
}
private bool ShouldRenderAxes()
{
var pieType = typeof(RadzenPieSeries<>);
var donutType = typeof(RadzenDonutSeries<>);
return !Series.All(series =>
{
var type = series.GetType().GetGenericTypeDefinition();
return type == pieType || type == donutType;
});
}
internal bool ShouldInvertAxes()
{
return Series.Count > 0 && Series.All(series => series is IChartBarSeries);
}
private bool UpdateScales()
{
var valueScale = ValueScale;
var categoryScale = CategoryScale;
CategoryScale = new LinearScale { Output = CategoryScale.Output };
ValueScale = new LinearScale { Output = ValueScale.Output };
var visibleSeries = Series.Where(series => series.Visible).ToList();
if (!visibleSeries.Any() && invisibleSeries.Any())
{
visibleSeries.Add(invisibleSeries.Last());
}
foreach (var series in visibleSeries)
{
CategoryScale = series.TransformCategoryScale(CategoryScale);
ValueScale = series.TransformValueScale(ValueScale);
}
AxisBase xAxis = CategoryAxis;
AxisBase yAxis = ValueAxis;
if (ShouldInvertAxes())
{
xAxis = ValueAxis;
yAxis = CategoryAxis;
}
else
{
CategoryScale.Padding = CategoryAxis.Padding;
}
CategoryScale.Resize(xAxis.Min, xAxis.Max);
if (xAxis.Step != null)
{
CategoryScale.Step = xAxis.Step;
CategoryScale.Round = false;
}
ValueScale.Resize(yAxis.Min, yAxis.Max);
if (yAxis.Step != null)
{
ValueScale.Step = yAxis.Step;
ValueScale.Round = false;
}
var legendSize = Legend.Measure(this);
var valueAxisSize = ValueAxis.Measure(this);
var categoryAxisSize = CategoryAxis.Measure(this);
if (!ShouldRenderAxes())
{
valueAxisSize = categoryAxisSize = 0;
}
MarginTop = MarginRight = 32;
MarginLeft = valueAxisSize;
MarginBottom = Math.Max(32, categoryAxisSize);
if (Legend.Visible)
{
if (Legend.Position == LegendPosition.Right || Legend.Position == LegendPosition.Left)
{
if (Legend.Position == LegendPosition.Right)
{
MarginRight = legendSize + 16;
}
else
{
MarginLeft = legendSize + 16 + valueAxisSize;
}
}
else if (Legend.Position == LegendPosition.Top || Legend.Position == LegendPosition.Bottom)
{
if (Legend.Position == LegendPosition.Top)
{
MarginTop = legendSize + 16;
}
else
{
MarginBottom = legendSize + 16 + categoryAxisSize;
}
}
}
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
ValueScale.Fit(ValueAxis.TickDistance);
CategoryScale.Fit(CategoryAxis.TickDistance);
var stateHasChanged = false;
if (!ValueScale.IsEqualTo(valueScale))
{
stateHasChanged = true;
}
if (!CategoryScale.IsEqualTo(categoryScale))
{
stateHasChanged = true;
}
return stateHasChanged;
}
[JSInvokable]
public void Resize(double width, double height)
{
var stateHasChanged = false;
if (width != Width)
{
Width = width;
stateHasChanged = true;
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
}
if (height != Height)
{
Height = height;
stateHasChanged = true;
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
}
if (stateHasChanged)
{
Refresh();
}
}
RenderFragment tooltip;
object tooltipData;
double mouseX;
double mouseY;
[JSInvokable]
public void MouseMove(double x, double y)
{
mouseX = x;
mouseY = y;
DisplayTooltip();
}
internal void DisplayTooltip()
{
if (Tooltip.Visible)
{
foreach (var series in Series)
{
if (series.Visible && series.Contains(mouseX - MarginLeft, mouseY - MarginTop))
{
var data = series.DataAt(mouseX - MarginLeft, mouseY - MarginTop);
if (data != tooltipData)
{
tooltipData = data;
tooltip = series.RenderTooltip(data, MarginLeft, MarginTop);
StateHasChanged();
}
return;
}
}
if (tooltip != null)
{
tooltipData = null;
tooltip = null;
StateHasChanged();
}
}
}
private IList<IChartSeries> invisibleSeries = new List<IChartSeries>();
internal void ToggleSeries(IChartSeries series)
{
series.Visible = !series.Visible;
if (series.Visible)
{
invisibleSeries.Remove(series);
}
else
{
invisibleSeries.Add(series);
}
Refresh();
}
private bool widthAndHeightAreSet = false;
private bool firstRender = true;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
this.firstRender = firstRender;
if (firstRender || visibleChanged)
{
visibleChanged = false;
if (Visible)
{
var rect = await JSRuntime.InvokeAsync<Rect>("Radzen.createChart", Element, Reference);
if (!widthAndHeightAreSet)
{
widthAndHeightAreSet = true;
Resize(rect.Width, rect.Height);
}
}
}
}
internal string ClipPath { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
ClipPath = $"clipPath{UniqueID}";
CategoryAxis.Chart = this;
ValueAxis.Chart = this;
Initialize();
}
private void Initialize()
{
double width = 0;
double height = 0;
if (CurrentStyle.ContainsKey("height"))
{
var pixelHeight = CurrentStyle["height"];
if (pixelHeight.EndsWith("px"))
{
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()));
}
}
if (CurrentStyle.ContainsKey("width"))
{
var pixelWidth = CurrentStyle["width"];
if (pixelWidth.EndsWith("px"))
{
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()));
}
}
if (width > 0 && height > 0)
{
widthAndHeightAreSet = true;
Width = width;
Height = height;
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
}
}
private bool visibleChanged = false;
public override async Task SetParametersAsync(ParameterView parameters)
{
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
await base.SetParametersAsync(parameters);
if (shouldRefresh)
{
Initialize();
}
if (visibleChanged && !firstRender)
{
if (Visible == false)
{
await JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
}
}
}
internal void Refresh(bool force = true)
{
if (widthAndHeightAreSet)
{
var stateHasChanged = UpdateScales();
if (stateHasChanged || force)
{
StateHasChanged();
}
}
}
public void Reload()
{
Refresh(true);
}
public override void Dispose()
{
base.Dispose();
if (Visible && IsJSRuntimeAvailable)
{
JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
}
}
protected override string GetComponentCssClass()
{
return $"rz-chart rz-scheme-{ColorScheme.ToString().ToLower()}";
}
}

View File

@@ -0,0 +1,495 @@
using Microsoft.JSInterop;
using Radzen.Blazor.Rendering;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
namespace Radzen.Blazor
{
/// <summary>
/// Displays line, area, donut, pie, bar or column series.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenChart&gt;
/// &lt;RadzenColumnSeries Data=@revenue CategoryProperty="Quarter" ValueProperty="Revenue" /&gt;
/// &lt;/RadzenChart&gt;
/// @code {
/// class DataItem
/// {
/// public string Quarter { get; set; }
/// public double Revenue { get; set; }
/// }
/// DataItem[] revenue = new DataItem[]
/// {
/// new DataItem { Quarter = "Q1", Revenue = 234000 },
/// new DataItem { Quarter = "Q2", Revenue = 284000 },
/// new DataItem { Quarter = "Q3", Revenue = 274000 },
/// new DataItem { Quarter = "Q4", Revenue = 294000 }
/// };
/// }
/// </code>
/// </example>
public partial class RadzenChart : RadzenComponent
{
/// <summary>
/// Gets or sets the color scheme used to render the series.
/// </summary>
/// <value>The color scheme.</value>
[Parameter]
public ColorScheme ColorScheme { get; set; }
/// <summary>
/// A callback that will be invoked when the user clicks on a series.
/// </summary>
[Parameter]
public EventCallback<SeriesClickEventArgs> SeriesClick { get; set; }
/// <summary>
/// A callback that will be invoked when the user clicks on a legend.
/// </summary>
[Parameter]
public EventCallback<LegendClickEventArgs> LegendClick { get; set; }
double? Width { get; set; }
double? Height { get; set; }
double MarginTop { get; set; }
double MarginLeft { get; set; }
double MarginRight { get; set; }
double MarginBottom { get; set; }
/// <summary>
/// Gets or sets the child content. Used to specify series and other configuration.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
internal ScaleBase CategoryScale { get; set; } = new LinearScale();
internal ScaleBase ValueScale { get; set; } = new LinearScale();
internal IList<IChartSeries> Series { get; set; } = new List<IChartSeries>();
internal RadzenColumnOptions ColumnOptions { get; set; } = new RadzenColumnOptions();
internal RadzenBarOptions BarOptions { get; set; } = new RadzenBarOptions();
internal RadzenLegend Legend { get; set; } = new RadzenLegend();
internal RadzenCategoryAxis CategoryAxis { get; set; } = new RadzenCategoryAxis();
internal RadzenValueAxis ValueAxis { get; set; } = new RadzenValueAxis();
internal RadzenChartTooltipOptions Tooltip { get; set; } = new RadzenChartTooltipOptions();
internal void AddSeries(IChartSeries series)
{
if (!Series.Contains(series))
{
Series.Add(series);
}
}
internal void RemoveSeries(IChartSeries series)
{
Series.Remove(series);
}
private bool ShouldRenderAxes()
{
var pieType = typeof(RadzenPieSeries<>);
var donutType = typeof(RadzenDonutSeries<>);
return !Series.All(series =>
{
var type = series.GetType().GetGenericTypeDefinition();
return type == pieType || type == donutType;
});
}
internal bool ShouldInvertAxes()
{
return Series.Count > 0 && Series.All(series => series is IChartBarSeries);
}
private bool UpdateScales()
{
var valueScale = ValueScale;
var categoryScale = CategoryScale;
CategoryScale = new LinearScale { Output = CategoryScale.Output };
ValueScale = new LinearScale { Output = ValueScale.Output };
var visibleSeries = Series.Where(series => series.Visible).ToList();
var invisibleSeries = Series.Where(series => series.Visible == false).ToList();
if (!visibleSeries.Any() && invisibleSeries.Any())
{
visibleSeries.Add(invisibleSeries.Last());
}
foreach (var series in visibleSeries)
{
CategoryScale = series.TransformCategoryScale(CategoryScale);
ValueScale = series.TransformValueScale(ValueScale);
}
AxisBase xAxis = CategoryAxis;
AxisBase yAxis = ValueAxis;
if (ShouldInvertAxes())
{
xAxis = ValueAxis;
yAxis = CategoryAxis;
}
else
{
CategoryScale.Padding = CategoryAxis.Padding;
}
CategoryScale.Resize(xAxis.Min, xAxis.Max);
if (xAxis.Step != null)
{
CategoryScale.Step = xAxis.Step;
CategoryScale.Round = false;
}
ValueScale.Resize(yAxis.Min, yAxis.Max);
if (yAxis.Step != null)
{
ValueScale.Step = yAxis.Step;
ValueScale.Round = false;
}
var legendSize = Legend.Measure(this);
var valueAxisSize = ValueAxis.Measure(this);
var categoryAxisSize = CategoryAxis.Measure(this);
if (!ShouldRenderAxes())
{
valueAxisSize = categoryAxisSize = 0;
}
MarginTop = MarginRight = 32;
MarginLeft = valueAxisSize;
MarginBottom = Math.Max(32, categoryAxisSize);
if (Legend.Visible)
{
if (Legend.Position == LegendPosition.Right || Legend.Position == LegendPosition.Left)
{
if (Legend.Position == LegendPosition.Right)
{
MarginRight = legendSize + 16;
}
else
{
MarginLeft = legendSize + 16 + valueAxisSize;
}
}
else if (Legend.Position == LegendPosition.Top || Legend.Position == LegendPosition.Bottom)
{
if (Legend.Position == LegendPosition.Top)
{
MarginTop = legendSize + 16;
}
else
{
MarginBottom = legendSize + 16 + categoryAxisSize;
}
}
}
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
ValueScale.Fit(ValueAxis.TickDistance);
CategoryScale.Fit(CategoryAxis.TickDistance);
var stateHasChanged = false;
if (!ValueScale.IsEqualTo(valueScale))
{
stateHasChanged = true;
}
if (!CategoryScale.IsEqualTo(categoryScale))
{
stateHasChanged = true;
}
return stateHasChanged;
}
/// <summary>
/// Invoked via interop when the RadzenChart resizes. Display the series with the new dimensions.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
[JSInvokable]
public async Task Resize(double width, double height)
{
var stateHasChanged = false;
if (width != Width)
{
Width = width;
stateHasChanged = true;
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
}
if (height != Height)
{
Height = height;
stateHasChanged = true;
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
}
if (stateHasChanged)
{
await Refresh();
}
}
RenderFragment tooltip;
object tooltipData;
double mouseX;
double mouseY;
/// <summary>
/// Invoked via interop when the user moves the mouse over the RadzenChart. Displays the tooltip.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
[JSInvokable]
public async Task MouseMove(double x, double y)
{
mouseX = x;
mouseY = y;
await DisplayTooltip();
}
/// <summary>
/// Invoked via interop when the user clicks the RadzenChart. Raises the <see cref="SeriesClick" /> handler.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
[JSInvokable]
public async Task Click(double x, double y)
{
foreach (var series in Series)
{
if (series.Visible && series.Contains(mouseX - MarginLeft, mouseY - MarginTop, 5))
{
var data = series.DataAt(mouseX - MarginLeft, mouseY - MarginTop);
if (data != null)
{
await series.InvokeClick(SeriesClick, data);
}
return;
}
}
}
internal async Task DisplayTooltip()
{
if (Tooltip.Visible)
{
var orderedSeries = Series.OrderBy(s => s.RenderingOrder).Reverse();
foreach (var series in orderedSeries)
{
if (series.Visible)
{
foreach (var overlay in series.Overlays.Reverse())
{
if (overlay.Visible && overlay.Contains(mouseX - MarginLeft, mouseY - MarginTop, 25))
{
tooltipData = null;
tooltip = overlay.RenderTooltip(mouseX, mouseY, MarginLeft, MarginTop);
StateHasChanged();
await Task.Yield();
return;
}
}
if (series.Contains(mouseX - MarginLeft, mouseY - MarginTop, 25))
{
var data = series.DataAt(mouseX - MarginLeft, mouseY - MarginTop);
if (data != tooltipData)
{
tooltipData = data;
tooltip = series.RenderTooltip(data, MarginLeft, MarginTop);
StateHasChanged();
await Task.Yield();
}
return;
}
}
}
if (tooltip != null)
{
tooltipData = null;
tooltip = null;
StateHasChanged();
await Task.Yield();
}
}
}
private bool widthAndHeightAreSet = false;
private bool firstRender = true;
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
this.firstRender = firstRender;
if (firstRender || visibleChanged)
{
visibleChanged = false;
if (Visible)
{
var rect = await JSRuntime.InvokeAsync<Rect>("Radzen.createChart", Element, Reference);
if (!widthAndHeightAreSet)
{
widthAndHeightAreSet = true;
await Resize(rect.Width, rect.Height);
}
}
}
}
internal string ClipPath { get; set; }
/// <inheritdoc />
protected override void OnInitialized()
{
base.OnInitialized();
ClipPath = $"clipPath{UniqueID}";
CategoryAxis.Chart = this;
ValueAxis.Chart = this;
Initialize();
}
private void Initialize()
{
double width = 0;
double height = 0;
if (CurrentStyle.ContainsKey("height"))
{
var pixelHeight = CurrentStyle["height"];
if (pixelHeight.EndsWith("px"))
{
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()));
}
}
if (CurrentStyle.ContainsKey("width"))
{
var pixelWidth = CurrentStyle["width"];
if (pixelWidth.EndsWith("px"))
{
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()));
}
}
if (width > 0 && height > 0)
{
widthAndHeightAreSet = true;
Width = width;
Height = height;
CategoryScale.Output = new ScaleRange { Start = MarginLeft, End = Width.Value - MarginRight };
ValueScale.Output = new ScaleRange { Start = Height.Value - MarginBottom, End = MarginTop };
}
}
private bool visibleChanged = false;
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
bool shouldRefresh = parameters.DidParameterChange(nameof(Style), Style);
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
await base.SetParametersAsync(parameters);
if (shouldRefresh)
{
Initialize();
}
if (visibleChanged && !firstRender)
{
if (Visible == false)
{
await JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
}
}
}
internal async Task Refresh(bool force = true)
{
if (widthAndHeightAreSet)
{
var stateHasChanged = UpdateScales();
if (stateHasChanged || force)
{
StateHasChanged();
await DisplayTooltip();
}
}
}
/// <summary>
/// Causes all series to refresh. Use it when <see cref="CartesianSeries{TItem}.Data" /> has changed.
/// </summary>
public async Task Reload()
{
await Refresh(true);
}
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
if (Visible && IsJSRuntimeAvailable)
{
JSRuntime.InvokeVoidAsync("Radzen.destroyChart", Element);
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return $"rz-chart rz-scheme-{ColorScheme.ToString().ToLowerInvariant()}";
}
}
}

View File

@@ -1,13 +1,19 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Base class of components that are rendered inside a <see cref="RadzenChart" />.
/// </summary>
public abstract class RadzenChartComponentBase : ComponentBase
{
private RadzenChart chart;
/// <summary>
/// Used to inject the RadzenChart instance. Invokes <see cref="Initialize" />.
/// </summary>
/// <value>The chart.</value>
[CascadingParameter]
public RadzenChart Chart
{
@@ -22,16 +28,24 @@ namespace Radzen.Blazor
}
}
/// <summary>
/// Perform initialization when <see cref="Chart" /> is set.
/// </summary>
protected virtual void Initialize()
{
}
/// <summary>
/// Determines if RadzenChart should render.
/// </summary>
/// <param name="parameters">The parameters.</param>
protected virtual bool ShouldRefreshChart(ParameterView parameters)
{
return false;
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
bool shouldRefresh = ShouldRefreshChart(parameters);
@@ -42,14 +56,25 @@ namespace Radzen.Blazor
if (shouldRefresh)
{
Chart.Refresh();
await Chart.Refresh();
}
}
/// <summary>
/// Validates the parameters.
/// </summary>
protected virtual void ValidateParameters()
{
}
/// <summary>
/// Checks if the specified parameter changed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="parameters">The parameters.</param>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="parameterValue">The parameter value.</param>
/// <returns><c>true</c> if the parameter changed, <c>false</c> otherwise.</returns>
protected bool DidParameterChange<T>(ParameterView parameters, string parameterName, T parameterValue)
{
return parameters.DidParameterChange(parameterName, parameterValue);

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Contains <see cref="RadzenChart" /> tooltip configuration.
/// </summary>
public partial class RadzenChartTooltipOptions : RadzenChartComponentBase
{
/// <summary>
/// Gets or sets a value indicating whether to show tooltips. By defaults RadzenChart displays tooltips.
/// </summary>
/// <value><c>true</c> to display tooltips; otherwise, <c>false</c>.</value>
[Parameter]
public bool Visible { get; set; } = true;
/// <summary>
/// Gets or sets the CSS style of the tooltip.
/// </summary>
/// <value>The style.</value>
[Parameter]
public string Style { get; set; }
/// <inheritdoc />
protected override void Initialize()
{
Chart.Tooltip = this;
}
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return parameters.DidParameterChange(nameof(Style), Style);
}
}
}

View File

@@ -1,18 +0,0 @@
@inherits RadzenChartComponentBase
@code {
[Parameter]
public bool Visible { get; set; } = true;
[Parameter]
public string Style { get; set; }
protected override void Initialize()
{
Chart.Tooltip = this;
}
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return parameters.DidParameterChange(nameof(Style), Style);
}
}

View File

@@ -1,88 +1,17 @@
@using Radzen
@using Radzen.Blazor.Rendering
@using Microsoft.AspNetCore.Components.Forms
@typeparam TValue
@inherits FormComponent<TValue>
@if (Visible)
{
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()"
@onmouseup="@OnMouseUp" @onkeypress="@(async (args) => { if (args.Code == "Space") { await Toggle(); } })" style="@Style" tabindex="@TabIndex" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input type="text" name="@Name" value="@Value" tabindex="-1">
</div>
<div class="@getInnerCssClass()">
<span class="@getCheckBoxCssClass()"></span>
</div>
<div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" @onkeypress=@OnKeyPress @onkeypress:preventDefault style="@Style" tabindex="@TabIndex" id="@GetId()">
<div class="rz-helper-hidden-accessible">
<input type="checkbox" @onchange=@Toggle value=@CheckBoxValue name=@Name id=@Name checked=@CheckBoxChecked
tabindex="-1">
</div>
}
@code {
[Parameter]
public bool TriState { get; set; } = false;
string getInnerCssClass()
{
string activeState = !object.Equals(Value, false) ? " rz-state-active" : "";
string disabledState = Disabled ? " rz-state-disabled" : "";
return $"rz-chkbox-box {activeState}{disabledState}";
}
string getCheckBoxCssClass()
{
if (object.Equals(Value, true))
{
return "rz-chkbox-icon rzi rzi-check";
}
else if (object.Equals(Value, false))
{
return "rz-chkbox-icon";
}
else if (object.Equals(Value, null))
{
return "rz-chkbox-icon rzi rzi-times";
}
return "";
}
protected override string GetComponentCssClass()
{
var fieldCssClass = FieldIdentifier.FieldName != null ? EditContext?.FieldCssClass(FieldIdentifier) : "";
return $"rz-chkbox {(Disabled ? " rz-state-disabled" : "")} {fieldCssClass}";
}
public async Task OnMouseUp(MouseEventArgs args)
{
await Toggle();
}
async System.Threading.Tasks.Task Toggle()
{
if (Disabled)
{
return;
}
if (object.Equals(Value, false))
{
if (TriState)
{
Value = default(TValue);
}
else
{
Value = (TValue)(object)true;
}
}
else if (Value == null)
{
Value = (TValue)(object)true;
}
else if (object.Equals(Value, true))
{
Value = (TValue)(object)false;
}
await ValueChanged.InvokeAsync(Value);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
}
<div class=@BoxClassList @onclick=@Toggle @onclick:preventDefault>
<span class=@IconClassList></span>
</div>
</div>
}

View File

@@ -0,0 +1,84 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor.Rendering;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenCheckBox component.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <example>
/// <code>
/// &lt;RadzenCheckBox @bind-Value=@someValue TValue="bool" Change=@(args => Console.WriteLine($"Is checked: {args}")) /&gt;
/// </code>
/// </example>
public partial class RadzenCheckBox<TValue> : FormComponent<TValue>
{
/// <summary>
/// Gets or sets a value indicating whether is tri-state (true, false or null).
/// </summary>
/// <value><c>true</c> if tri-state; otherwise, <c>false</c>.</value>
[Parameter]
public bool TriState { get; set; } = false;
ClassList BoxClassList => ClassList.Create("rz-chkbox-box")
.Add("rz-state-active", !object.Equals(Value, false))
.AddDisabled(Disabled);
ClassList IconClassList => ClassList.Create("rz-chkbox-icon")
.Add("rzi rzi-check", object.Equals(Value, true))
.Add("rzi rzi-times", object.Equals(Value, null));
string CheckBoxValue => CheckBoxChecked ? "true" : "false";
bool CheckBoxChecked => object.Equals(Value, true);
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList("rz-chkbox").ToString();
}
async Task OnKeyPress(KeyboardEventArgs args)
{
if (args.Code == "Space")
{
await Toggle();
}
}
async Task Toggle()
{
if (Disabled)
{
return;
}
if (object.Equals(Value, false))
{
if (TriState)
{
Value = default;
}
else
{
Value = (TValue)(object)true;
}
}
else if (Value == null)
{
Value = (TValue)(object)true;
}
else if (object.Equals(Value, true))
{
Value = (TValue)(object)false;
}
await ValueChanged.InvokeAsync(Value);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
}
}
}

View File

@@ -1,6 +1,7 @@
@using System.Linq
@using System.Collections
@using Radzen
@using Radzen.Blazor.Rendering
@using Microsoft.AspNetCore.Components.Forms
@typeparam TValue
@inherits FormComponent<IEnumerable<TValue>>
@@ -21,138 +22,12 @@
<div class="rz-helper-hidden-accessible">
<input type="checkbox" name="@Name" value="@item.Value" disabled="@Disabled" tabindex="-1">
</div>
@if (IsSelected(item))
{
<div class="@($"rz-chkbox-box rz-state-active{getDisabledState(item)}")">
<span class="rz-chkbox-icon rzi rzi-check"></span>
</div>
}
else
{
<div class="@($"rz-chkbox-box {getDisabledState(item)}")">
<span class="rz-chkbox-icon "></span>
</div>
}
<div class=@ItemClassList(item)>
<span class=@IconClassList(item)></span>
</div>
</div>
<label class="rz-chkbox-label">@item.Text</label>
</div>
}
</div>
}
@code {
[Parameter]
public string ValueProperty { get; set; }
[Parameter]
public string TextProperty { get; set; }
IEnumerable<RadzenCheckBoxListItem<TValue>> allItems
{
get
{
return items.Concat((Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()).Select(i =>
{
var item = new RadzenCheckBoxListItem<TValue>();
item.SetText((string)PropertyAccess.GetItemOrValueFromProperty(i, TextProperty));
item.SetValue((TValue)PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty));
return item;
}));
}
}
IEnumerable _data = null;
[Parameter]
public virtual IEnumerable Data
{
get
{
return _data;
}
set
{
if (_data != value)
{
_data = value;
StateHasChanged();
}
}
}
protected override string GetComponentCssClass()
{
var fieldCssClass = FieldIdentifier.FieldName != null ? EditContext?.FieldCssClass(FieldIdentifier) : "";
return $"{(Orientation == Orientation.Horizontal ? "rz-checkbox-list-horizontal" : "rz-checkbox-list-vertical")} {fieldCssClass}";
}
public override bool HasValue
{
get
{
return Value != null && Value.Any();
}
}
[Parameter]
public Orientation Orientation { get; set; } = Orientation.Horizontal;
[Parameter]
public RenderFragment Items { get; set; }
List<RadzenCheckBoxListItem<TValue>> items = new List<RadzenCheckBoxListItem<TValue>>();
public void AddItem(RadzenCheckBoxListItem<TValue> item)
{
if (items.IndexOf(item) == -1)
{
items.Add(item);
StateHasChanged();
}
}
public void RemoveItem(RadzenCheckBoxListItem<TValue> item)
{
if (items.Contains(item))
{
items.Remove(item);
try { InvokeAsync(StateHasChanged); } catch { }
}
}
protected bool IsSelected(RadzenCheckBoxListItem<TValue> item)
{
return Value != null && Value.Contains(item.Value);
}
protected async System.Threading.Tasks.Task SelectItem(RadzenCheckBoxListItem<TValue> item)
{
if (Disabled || item.Disabled)
return;
List<TValue> selectedValues = new List<TValue>(Value != null ? Value : Enumerable.Empty<TValue>());
if (!selectedValues.Contains(item.Value))
{
selectedValues.Add(item.Value);
}
else
{
selectedValues.Remove(item.Value);
}
Value = selectedValues;
await ValueChanged.InvokeAsync(Value);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
StateHasChanged();
}
private string getDisabledState(RadzenCheckBoxListItem<TValue> item)
{
return Disabled || item.Disabled ? " rz-state-disabled" : "";
}
}

View File

@@ -0,0 +1,191 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Radzen.Blazor.Rendering;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenCheckBoxList component.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <example>
/// <code>
/// &lt;RadzenCheckBoxList @bind-Value=@checkedValues TValue="int" &gt;
/// &lt;Items&gt;
/// &lt;RadzenCheckBoxListItem Text="Orders" Value="1" /&gt;
/// &lt;RadzenCheckBoxListItem Text="Employees" Value="2" /&gt;
/// &lt;/Items&gt;
/// &lt;/RadzenCheckBoxList&gt;
/// </code>
/// </example>
public partial class RadzenCheckBoxList<TValue> : FormComponent<IEnumerable<TValue>>
{
ClassList ItemClassList(RadzenCheckBoxListItem<TValue> item) => ClassList.Create("rz-chkbox-box")
.Add("rz-state-active", IsSelected(item))
.AddDisabled(Disabled || item.Disabled);
ClassList IconClassList(RadzenCheckBoxListItem<TValue> item) => ClassList.Create("rz-chkbox-icon")
.Add("rzi rzi-check", IsSelected(item));
/// <summary>
/// Gets or sets the value property.
/// </summary>
/// <value>The value property.</value>
[Parameter]
public string ValueProperty { get; set; }
/// <summary>
/// Gets or sets the text property.
/// </summary>
/// <value>The text property.</value>
[Parameter]
public string TextProperty { get; set; }
IEnumerable<RadzenCheckBoxListItem<TValue>> allItems
{
get
{
return items.Concat((Data != null ? Data.Cast<object>() : Enumerable.Empty<object>()).Select(i =>
{
var item = new RadzenCheckBoxListItem<TValue>();
item.SetText((string)PropertyAccess.GetItemOrValueFromProperty(i, TextProperty));
item.SetValue((TValue)PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty));
return item;
}));
}
}
IEnumerable _data = null;
/// <summary>
/// Gets or sets the data used to generate items.
/// </summary>
/// <value>The data.</value>
[Parameter]
public virtual IEnumerable Data
{
get
{
return _data;
}
set
{
if (_data != value)
{
_data = value;
StateHasChanged();
}
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
return GetClassList(Orientation == Orientation.Horizontal ? "rz-checkbox-list-horizontal" : "rz-checkbox-list-vertical").ToString();
}
/// <summary>
/// Gets a value indicating whether this instance has value.
/// </summary>
/// <value><c>true</c> if this instance has value; otherwise, <c>false</c>.</value>
public override bool HasValue
{
get
{
return Value != null && Value.Any();
}
}
/// <summary>
/// Gets or sets the orientation.
/// </summary>
/// <value>The orientation.</value>
[Parameter]
public Orientation Orientation { get; set; } = Orientation.Horizontal;
/// <summary>
/// Gets or sets the items that will be concatenated with generated items from Data.
/// </summary>
/// <value>The items.</value>
[Parameter]
public RenderFragment Items { get; set; }
List<RadzenCheckBoxListItem<TValue>> items = new List<RadzenCheckBoxListItem<TValue>>();
/// <summary>
/// Adds the item.
/// </summary>
/// <param name="item">The item.</param>
public void AddItem(RadzenCheckBoxListItem<TValue> item)
{
if (items.IndexOf(item) == -1)
{
items.Add(item);
StateHasChanged();
}
}
/// <summary>
/// Removes the item.
/// </summary>
/// <param name="item">The item.</param>
public void RemoveItem(RadzenCheckBoxListItem<TValue> item)
{
if (items.Contains(item))
{
items.Remove(item);
if (!disposed)
{
try { InvokeAsync(StateHasChanged); } catch { }
}
}
}
/// <summary>
/// Determines whether the specified item is selected.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if the specified item is selected; otherwise, <c>false</c>.</returns>
protected bool IsSelected(RadzenCheckBoxListItem<TValue> item)
{
return Value != null && Value.Contains(item.Value);
}
/// <summary>
/// Selects the item.
/// </summary>
/// <param name="item">The item.</param>
protected async System.Threading.Tasks.Task SelectItem(RadzenCheckBoxListItem<TValue> item)
{
if (Disabled || item.Disabled)
return;
List<TValue> selectedValues = new List<TValue>(Value != null ? Value : Enumerable.Empty<TValue>());
if (!selectedValues.Contains(item.Value))
{
selectedValues.Add(item.Value);
}
else
{
selectedValues.Remove(item.Value);
}
Value = selectedValues;
await ValueChanged.InvokeAsync(Value);
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
await Change.InvokeAsync(Value);
StateHasChanged();
}
private string getDisabledState(RadzenCheckBoxListItem<TValue> item)
{
return Disabled || item.Disabled ? " rz-state-disabled" : "";
}
}
}

View File

@@ -0,0 +1,74 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenCheckBoxListItem component.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
public partial class RadzenCheckBoxListItem<TValue> : RadzenComponent
{
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
[Parameter]
public string Text { get; set; }
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Parameter]
public TValue Value { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="RadzenCheckBoxListItem{TValue}"/> is disabled.
/// </summary>
/// <value><c>true</c> if disabled; otherwise, <c>false</c>.</value>
[Parameter]
public virtual bool Disabled { get; set; }
RadzenCheckBoxList<TValue> _checkBoxList;
/// <summary>
/// Gets or sets the CheckBox list.
/// </summary>
/// <value>The CheckBox list.</value>
[CascadingParameter]
public RadzenCheckBoxList<TValue> CheckBoxList
{
get
{
return _checkBoxList;
}
set
{
if (_checkBoxList != value)
{
_checkBoxList = value;
_checkBoxList.AddItem(this);
}
}
}
/// <summary>
/// Disposes this instance.
/// </summary>
public override void Dispose()
{
base.Dispose();
CheckBoxList?.RemoveItem(this);
}
internal void SetText(string value)
{
Text = value;
}
internal void SetValue(TValue value)
{
Value = value;
}
}
}

View File

@@ -1,47 +0,0 @@
@typeparam TValue
@inherits RadzenComponent
@code {
[Parameter]
public string Text { get; set; }
[Parameter]
public TValue Value { get; set; }
[Parameter]
public virtual bool Disabled { get; set; }
RadzenCheckBoxList<TValue> _checkBoxList;
[CascadingParameter]
public RadzenCheckBoxList<TValue> CheckBoxList
{
get
{
return _checkBoxList;
}
set
{
if (_checkBoxList != value)
{
_checkBoxList = value;
_checkBoxList.AddItem(this);
}
}
}
public override void Dispose()
{
base.Dispose();
CheckBoxList?.RemoveItem(this);
}
internal void SetText(string value)
{
Text = value;
}
internal void SetValue(TValue value)
{
Value = value;
}
}

View File

@@ -11,23 +11,23 @@
<i class="rzi">@Icon</i>
}
<div class="rz-colorpicker-value" style="background-color: @Color" ></div>
<button type="button" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="rzi" /></button>
<button type="button" tabindex="-1" class="rz-colorpicker-trigger" disabled=@Disabled @onclick:preventDefault><i class="rzi" /></button>
<Popup @ref=@Popup class="rz-colorpicker-popup" Close=@Close Open=@Open>
@if (ShowHSV)
{
<Draggable class="rz-saturation-picker rz-colorpicker-section" style=@($"background-color: {HSV.ToRGB().ToCSS()}") Drag=@OnSaturationMove>
<div class="rz-saturation-white">
<div class="rz-saturation-black"></div>
<div class="rz-saturation-handle" style=@($"top: {SaturationHandleTop*100}%; left: {SaturationHandleLeft * 100}%")></div>
<div class="rz-saturation-handle" style=@($"top: {(SaturationHandleTop*100).ToInvariantString()}%; left: {(SaturationHandleLeft * 100).ToInvariantString()}%")></div>
</div>
</Draggable>
<div class="rz-colorpicker-preview-area rz-colorpicker-section">
<div class="rz-hue-and-alpha">
<Draggable class="rz-hue-picker" Drag=@OnHueMove>
<div class="rz-hue-handle" style=@($"top: 0; left: {HueHandleLeft * 100}%")></div>
<div class="rz-hue-handle" style=@($"top: 0; left: {(HueHandleLeft * 100).ToInvariantString()}%")></div>
</Draggable>
<Draggable style=@($"background-image: linear-gradient(to right, {AlphaGradientStart} 0%, {AlphaGradientEnd} 100%)") class="rz-alpha-picker" Drag=@OnAlphaMove>
<div class="rz-alpha-handle" style=@($"top: 0; left: {AlphaHandleLeft * 100}%")></div>
<div class="rz-alpha-handle" style=@($"top: 0; left: {(AlphaHandleLeft * 100).ToInvariantString()}%")></div>
</Draggable>
</div>
<div class="rz-colorpicker-preview" style=@($"background-color: {Color}")></div>
@@ -110,334 +110,9 @@
@if(ShowButton)
{
<div class="rz-colorpicker-button rz-colorpicker-section">
<RadzenButton ButtonStyle="ButtonStyle.Secondary" Click=@OnClick Text=@ButtonText @onclick:preventDefault />
<RadzenButton ButtonStyle="ButtonStyle.Primary" Click=@OnClick Text=@ButtonText @onclick:preventDefault />
</div>
}
</Popup>
</div>
}
@code {
[Parameter]
public EventCallback Open { get; set; }
[Parameter]
public EventCallback Close { get; set; }
[Parameter]
public string Icon {get; set;}
[Parameter]
public string HexText { get; set; } = "Hex";
[Parameter]
public string RedText { get; set; } = "R";
[Parameter]
public string GreenText { get; set; } = "G";
[Parameter]
public string BlueText { get; set; } = "B";
[Parameter]
public string AlphaText { get; set; } = "A";
[Parameter]
public string ButtonText { get; set; } = "OK";
Popup Popup { get; set; }
string AlphaGradientStart
{
get
{
var rgb = RGB.Parse(Color);
rgb.Alpha = 0;
return rgb.ToCSS();
}
}
string AlphaGradientEnd
{
get
{
var rgb = RGB.Parse(Color);
rgb.Alpha = 1;
return rgb.ToCSS();
}
}
string Hex
{
get
{
var rgb = RGB.Parse(Color);
if (rgb != null)
{
return rgb.ToHex();
}
return String.Empty;
}
}
double Red
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Red;
}
}
double Alpha
{
get
{
return Math.Round(AlphaHandleLeft * 100);
}
}
double Green
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Green;
}
}
double Blue
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Blue;
}
}
void OnSaturationMove(DraggableEventArgs args)
{
SaturationHandleLeft = Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1);
SaturationHandleTop = Math.Clamp((args.ClientY - args.Rect.Top) / args.Rect.Height, 0, 1);
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
void TriggerChange()
{
if (!ShowButton)
{
ValueChanged.InvokeAsync(Color);
Change.InvokeAsync(Color);
}
StateHasChanged();
}
void ChangeRGB(object value)
{
SetValue(value as string);
}
void SetValue(string value)
{
var rgb = RGB.Parse(value);
if (rgb != null)
{
Color = rgb.ToCSS();
UpdateColor(rgb);
}
}
internal async Task SelectColor(string value)
{
SetValue(value);
if (!ShowButton)
{
await Popup.CloseAsync();
}
}
void UpdateColor(RGB rgb)
{
Color = rgb.ToCSS();
HSV = rgb.ToHSV();
SaturationHandleLeft = HSV.Saturation;
SaturationHandleTop = 1 - HSV.Value;
HueHandleLeft = HSV.Hue;
TriggerChange();
}
void ChangeAlpha(double value)
{
if (value >= 0 && value <= 100)
{
var rgb = RGB.Parse(Color);
AlphaHandleLeft = rgb.Alpha = Math.Round(value / 100, 2);
Color = rgb.ToCSS();
TriggerChange();
}
}
void ChangeAlpha(object alpha)
{
if (Double.TryParse((string)alpha, out var value))
{
ChangeAlpha(value);
}
}
void ChangeColor(double value, Action<RGB, double> update)
{
if (value >= 0 && value <= 255)
{
var rgb = RGB.Parse(Color);
update(rgb, value);
UpdateColor(rgb);
}
}
void ChangeColor(object color, Action<RGB, double> update)
{
if (Double.TryParse((string)color, out var value))
{
ChangeColor(value, update);
}
}
void OnAlphaMove(DraggableEventArgs args)
{
AlphaHandleLeft = Math.Round(Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1), 2);
HSV.Alpha = AlphaHandleLeft;
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
void OnHueMove(DraggableEventArgs args)
{
HueHandleLeft = Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1);
HSV.Hue = HueHandleLeft;
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
async Task OnClick()
{
await ValueChanged.InvokeAsync(Color);
await Change.InvokeAsync(Color);
await Popup.CloseAsync();
}
[Parameter]
public bool ShowButton { get; set; }
[Parameter]
public bool ShowHSV { get; set; } = true;
[Parameter]
public bool ShowRGBA { get; set; } = true;
[Parameter]
public bool ShowColors { get; set; } = true;
[Parameter]
public RenderFragment ChildContent { get; set; }
double SaturationHandleLeft { get; set; }
double HueHandleLeft { get; set; }
double AlphaHandleLeft { get; set; } = 1;
double SaturationHandleTop { get; set; }
HSV HSV { get; set; } = new HSV { Hue = 0, Saturation = 1, Value = 1 };
string Color { get; set; } = "rgb(255, 255, 255)";
async Task Toggle()
{
if (!Disabled)
{
await Popup.ToggleAsync(Element);
}
}
protected override string GetComponentCssClass()
{
var classList = new List<string>() { "rz-colorpicker" };
if (Disabled)
{
classList.Add("rz-disabled");
}
return string.Join(" ", classList);
}
protected override void OnInitialized()
{
Init();
base.OnInitialized();
}
void Init()
{
var value = Value;
if (String.IsNullOrEmpty(Value))
{
value = "rgb(255, 255, 255)";
}
if (value != Color)
{
Color = value;
HSV = RGB.Parse(Color).ToHSV();
SaturationHandleLeft = HSV.Saturation;
SaturationHandleTop = 1 - HSV.Value;
HSV.Saturation = 1;
HSV.Value = 1;
HueHandleLeft = HSV.Hue;
if (value.StartsWith("rgba"))
{
AlphaHandleLeft = HSV.Alpha;
}
}
}
public override async Task SetParametersAsync(ParameterView parameters)
{
var valueChanged = parameters.DidParameterChange(nameof(Value), Value);
await base.SetParametersAsync(parameters);
if (valueChanged)
{
Init();
}
}
}

View File

@@ -0,0 +1,398 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenColorPicker component.
/// </summary>
/// <example>
/// <code>
/// &lt;RadzenColorPicker @bind-Value=@color Change=@(args => Console.WriteLine($"Selected color: {args}")) /&gt;
/// </code>
/// </example>
public partial class RadzenColorPicker : FormComponent<string>
{
/// <summary>
/// Gets or sets the open callback.
/// </summary>
/// <value>The open callback.</value>
[Parameter]
public EventCallback Open { get; set; }
/// <summary>
/// Gets or sets the close callback.
/// </summary>
/// <value>The close callback.</value>
[Parameter]
public EventCallback Close { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>The icon.</value>
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Gets or sets the hexadecimal color label text.
/// </summary>
/// <value>The hexadecimal text.</value>
[Parameter]
public string HexText { get; set; } = "Hex";
/// <summary>
/// Gets or sets the red color label text.
/// </summary>
/// <value>The red text.</value>
[Parameter]
public string RedText { get; set; } = "R";
/// <summary>
/// Gets or sets the green color label text.
/// </summary>
/// <value>The green text.</value>
[Parameter]
public string GreenText { get; set; } = "G";
/// <summary>
/// Gets or sets the blue color label text.
/// </summary>
/// <value>The blue text.</value>
[Parameter]
public string BlueText { get; set; } = "B";
/// <summary>
/// Gets or sets the alpha label text.
/// </summary>
/// <value>The alpha text.</value>
[Parameter]
public string AlphaText { get; set; } = "A";
/// <summary>
/// Gets or sets the button text.
/// </summary>
/// <value>The button text.</value>
[Parameter]
public string ButtonText { get; set; } = "OK";
Popup Popup { get; set; }
string AlphaGradientStart
{
get
{
var rgb = RGB.Parse(Color);
rgb.Alpha = 0;
return rgb.ToCSS();
}
}
string AlphaGradientEnd
{
get
{
var rgb = RGB.Parse(Color);
rgb.Alpha = 1;
return rgb.ToCSS();
}
}
string Hex
{
get
{
var rgb = RGB.Parse(Color);
if (rgb != null)
{
return rgb.ToHex();
}
return String.Empty;
}
}
double Red
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Red;
}
}
double Alpha
{
get
{
return Math.Round(AlphaHandleLeft * 100);
}
}
double Green
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Green;
}
}
double Blue
{
get
{
var rgb = RGB.Parse(Color);
return rgb.Blue;
}
}
void OnSaturationMove(DraggableEventArgs args)
{
SaturationHandleLeft = Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1);
SaturationHandleTop = Math.Clamp((args.ClientY - args.Rect.Top) / args.Rect.Height, 0, 1);
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
void TriggerChange()
{
if (!ShowButton)
{
ValueChanged.InvokeAsync(Color);
Change.InvokeAsync(Color);
}
StateHasChanged();
}
void ChangeRGB(object value)
{
SetValue(value as string);
}
void SetValue(string value)
{
var rgb = RGB.Parse(value);
if (rgb != null)
{
Color = rgb.ToCSS();
UpdateColor(rgb);
}
}
internal async Task SelectColor(string value)
{
SetValue(value);
if (!ShowButton)
{
await Popup.CloseAsync();
}
}
void UpdateColor(RGB rgb)
{
Color = rgb.ToCSS();
HSV = rgb.ToHSV();
SaturationHandleLeft = HSV.Saturation;
SaturationHandleTop = 1 - HSV.Value;
HueHandleLeft = HSV.Hue;
TriggerChange();
}
void ChangeAlpha(double value)
{
if (value >= 0 && value <= 100)
{
var rgb = RGB.Parse(Color);
AlphaHandleLeft = rgb.Alpha = Math.Round(value / 100, 2);
Color = rgb.ToCSS();
TriggerChange();
}
}
void ChangeAlpha(object alpha)
{
if (Double.TryParse((string)alpha, out var value))
{
ChangeAlpha(value);
}
}
void ChangeColor(double value, Action<RGB, double> update)
{
if (value >= 0 && value <= 255)
{
var rgb = RGB.Parse(Color);
update(rgb, value);
UpdateColor(rgb);
}
}
void ChangeColor(object color, Action<RGB, double> update)
{
if (Double.TryParse((string)color, out var value))
{
ChangeColor(value, update);
}
}
void OnAlphaMove(DraggableEventArgs args)
{
AlphaHandleLeft = Math.Round(Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1), 2);
HSV.Alpha = AlphaHandleLeft;
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
void OnHueMove(DraggableEventArgs args)
{
HueHandleLeft = Math.Clamp((args.ClientX - args.Rect.Left) / args.Rect.Width, 0, 1);
HSV.Hue = HueHandleLeft;
var hsv = new HSV { Hue = HSV.Hue, Saturation = SaturationHandleLeft, Value = 1 - SaturationHandleTop, Alpha = AlphaHandleLeft };
Color = hsv.ToRGB().ToCSS();
TriggerChange();
}
async Task OnClick()
{
await ValueChanged.InvokeAsync(Color);
await Change.InvokeAsync(Color);
await Popup.CloseAsync();
}
/// <summary>
/// Gets or sets a value indicating whether button is shown.
/// </summary>
/// <value><c>true</c> if button shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowButton { get; set; }
/// <summary>
/// Gets or sets a value indicating whether HSV is shown.
/// </summary>
/// <value><c>true</c> if HSV is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowHSV { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether RGBA is shown.
/// </summary>
/// <value><c>true</c> if RGBA is shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowRGBA { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether colors are shown.
/// </summary>
/// <value><c>true</c> if colors are shown; otherwise, <c>false</c>.</value>
[Parameter]
public bool ShowColors { get; set; } = true;
/// <summary>
/// Gets or sets the child content.
/// </summary>
/// <value>The child content.</value>
[Parameter]
public RenderFragment ChildContent { get; set; }
double SaturationHandleLeft { get; set; }
double HueHandleLeft { get; set; }
double AlphaHandleLeft { get; set; } = 1;
double SaturationHandleTop { get; set; }
HSV HSV { get; set; } = new HSV { Hue = 0, Saturation = 1, Value = 1 };
string Color { get; set; } = "rgb(255, 255, 255)";
async Task Toggle()
{
if (!Disabled)
{
await Popup.ToggleAsync(Element);
}
}
/// <inheritdoc />
protected override string GetComponentCssClass()
{
var classList = new List<string>() { "rz-colorpicker" };
if (Disabled)
{
classList.Add("rz-disabled");
}
return string.Join(" ", classList);
}
/// <inheritdoc />
protected override void OnInitialized()
{
Init();
base.OnInitialized();
}
void Init()
{
var value = Value;
if (String.IsNullOrEmpty(Value))
{
value = "rgb(255, 255, 255)";
}
if (value != Color)
{
Color = value;
HSV = RGB.Parse(Color).ToHSV();
SaturationHandleLeft = HSV.Saturation;
SaturationHandleTop = 1 - HSV.Value;
HSV.Saturation = 1;
HSV.Value = 1;
HueHandleLeft = HSV.Hue;
if (value.StartsWith("rgba"))
{
AlphaHandleLeft = HSV.Alpha;
}
}
}
/// <inheritdoc />
public override async Task SetParametersAsync(ParameterView parameters)
{
var valueChanged = parameters.DidParameterChange(nameof(Value), Value);
await base.SetParametersAsync(parameters);
if (valueChanged)
{
Init();
}
}
}
}

View File

@@ -1,25 +1,3 @@
@using Radzen.Blazor.Rendering
<div class="rz-colorpicker-item" style="background-color: @Background" @onmousedown:preventDefault @onclick=@OnClick></div>
@code {
[Parameter]
public string Value { get; set; }
string Background
{
get
{
RGB rgb = RGB.Parse(Value);
return rgb?.ToCSS();
}
}
[CascadingParameter]
public RadzenColorPicker ColorPicker { get; set; }
async Task OnClick()
{
await ColorPicker.SelectColor(Value);
}
}

View File

@@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Components;
using Radzen.Blazor.Rendering;
using System.Threading.Tasks;
namespace Radzen.Blazor
{
/// <summary>
/// RadzenColorPickerItem component.
/// </summary>
public partial class RadzenColorPickerItem
{
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Parameter]
public string Value { get; set; }
string Background
{
get
{
RGB rgb = RGB.Parse(Value);
return rgb?.ToCSS();
}
}
/// <summary>
/// Gets or sets the color picker.
/// </summary>
/// <value>The color picker.</value>
[CascadingParameter]
public RadzenColorPicker ColorPicker { get; set; }
async Task OnClick()
{
await ColorPicker.SelectColor(Value);
}
}
}

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Components;
namespace Radzen.Blazor
{
/// <summary>
/// Common configuration of <see cref="RadzenColumnSeries{TItem}" />.
/// </summary>
public partial class RadzenColumnOptions : RadzenChartComponentBase
{
/// <summary>
/// Gets or sets the border radius of the bars.
/// </summary>
/// <value>The radius. Values greater than <c>0</c> make rounded corners.</value>
[Parameter]
public double Radius { get; set; }
/// <summary>
/// Gets or sets the margin between columns.
/// </summary>
/// <value>The margin. By default set to <c>10</c></value>
[Parameter]
public double Margin { get; set; } = 10;
/// <inheritdoc />
protected override void Initialize()
{
Chart.ColumnOptions = this;
}
/// <inheritdoc />
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
}
}
}

View File

@@ -1,18 +0,0 @@
@inherits RadzenChartComponentBase
@code {
[Parameter]
public double Radius { get; set; }
[Parameter]
public double Margin { get; set; } = 10;
protected override void Initialize()
{
Chart.ColumnOptions = this;
}
protected override bool ShouldRefreshChart(ParameterView parameters)
{
return DidParameterChange(parameters, nameof(Radius), Radius) || DidParameterChange(parameters, nameof(Margin), Margin);
}
}

Some files were not shown because too many files have changed in this diff Show More