Adding scrollbar to Telerik GridViewDataControl for expandable grid item - telerik

I have a Telerik:RadGridView that has items in it, some of which are expandable. The decision to make the row expandable is done in the RowLoaded event by setting the IsExpandable flag based on the type of object in the row. This works great.
To handle the row expansion, I have a method to handle the DataLoading event. It looks like this:
void AssignedNumbersGrid_DataLoading(object sender, GridViewDataLoadingEventArgs e)
{
GridViewDataControl dataControl = (GridViewDataControl)sender;
if (dataControl.ParentRow != null)
{
dataControl.ShowGroupPanel = false;
dataControl.AutoGenerateColumns = false;
dataControl.CanUserFreezeColumns = false;
dataControl.IsReadOnly = true;
dataControl.SelectionMode = System.Windows.Controls.SelectionMode.Extended;
dataControl.IsFilteringAllowed = false;
dataControl.ShowInsertRow = false;
dataControl.RowIndicatorVisibility = Visibility.Collapsed;
dataControl.ChildTableDefinitions.Clear();
dataControl.Margin = new Thickness(0, 0, 0, 0);
dataControl.EnableRowVirtualization = true;
dataControl.MaxHeight = 100;
ScrollViewer.SetVerticalScrollBarVisibility(dataControl, ScrollBarVisibility.Auto);
dataControl.Columns.Add(BuildSelectColumn());
dataControl.Columns.Add(BuildNewColumn("Range Number", "DisplayAssociatedInfo"));
dataControl.Columns.Add(BuildTypeColumn());
dataControl.Columns.Add(BuildRemarkColumn());
dataControl.Columns.Add(BuildNewColumn("Status", "DisplayStatus"));
}
}
I added the code to set the max height and the attached scroll viewer but the scroll bar does not show up. the dataControl object is of type GridViewDataControl, which is not the same as a RadGridView. Does anyone know how I can get a scroll bar to show on the expanded grid? The reason I need this is that the expanded grid may contain several hundred items and it takes several seconds to build the grid if it's large. I am thinking that with row virtualization and a scroll bar, it will be much faster.

Have you tried this:
<telerik:RadGrid ..>
.....
<ClientSettings EnableRowHoverStyle="True">
<Scrolling AllowScroll="True" EnableVirtualScrollPaging="True" SaveScrollPosition="True">
</Scrolling>
</ClientSettings>
</telerik:RadGrid>

I solved the problem by using a row details feature. The row details has another grid that contains the child items. The performance for this option is very fast.

Related

Custom Cell Format ListView TornadoFx on delete item

I'm new to TornadoFx but am trying it out (also new to JavaFX by extension).
I have a listview defined as so:
private var colorList = mutableListOf<Color>
//other things in init block
colorpicker(mode = ColorPickerMode.MenuButton) {
valueProperty().onChange {
if (it != null) {
colorList.add(it)
}
}
}(Color.BLACK,Color.WHITE).observable()
listview(colorList) {
cellFormat {
text = it.toString()
style {
baseColor = it
}
}
contextmenu {
item("Delete").action {
if (selectedItem != null) {
colorList.remove(selectedItem)
}
}
}
}
//continue init block
Adding and taking away colors from the listview works just fine but the color inside the cell does not disapear if it is no longer occupied
Example of what is happening
The cellFormat function allows you to configure the list cell for each item in your list.
However, when there is no list item for a certain row, the callback is not run, so that you have no way of applying a style to an empty row using the cellFormat approach. One solution would be to implement your own ListCell and always clearing the style property of the cell, but I believe this might actually be fixed within the framework by always clearing the style property before a cell is reused. I just tried to make this change in the framework, and it fixes the issue with your code sample.
I will commit the change now, please try it out with tornadofx-1.7.17-SNAPSHOT :)

Kendo Grid: Removing dirty cell indicators

I have been looking at a way to save off my client side edited grid data automatically when the user changes to another row (just like in access, sql management studio etc). It really seems to be a bit of a challenge to do.
One scheme was to use the data source sync, but this ha the problem of loosing our cell position (it always jumped to cell 0, 0).
I have been shown some clever work arounds (go back to the cell after the case, which by the way is hugely appreciated thanks),
but it after some lengthy testing (by myself and others) seemed to be a little "glitchy" (perhaps I just need to work on this more)
At any rate, I wanted to explore perhaps not using this datasource sync and perhaps just do the server side calls "manually" (which is a bit is a pity, but if that's what we need to do, so be it). If I do this, I would want to reset the cell little red cell "dirty" indicators.
I thought I could use something similar to this scheme (except rather than resetting the flag, I want to unset).
So, as in the above link, I have the following..
var pendingChanges = [];
function gridEdit(e) {
var cellHeader = $("#gridID").find("th[data-field='" + e.field + "']");
if (cellHeader[0] != undefined) {
var pendingChange = new Object();
pendingChange.PropertyName = e.field;
pendingChange.ColumnIndex = cellHeader[0].cellIndex;
pendingChange.uid = e.items[0].uid;
pendingChanges.push(pendingChange);
}
}
where we call gridEdit from the datasource change..
var dataSrc = new kendo.data.DataSource({
change: function (e) {
gridEdit(e);
},
Now assuming we have a callback that detects the row change, I thought I could do the following...
// clear cell property (red indicator)
for (var i = 0; i < pendingChanges.length; i++) {
var row = grid.tbody.find("tr[data-uid='" + pendingChanges[i].uid + "']");
var cell = row.find("td:eq(" + pendingChanges[i].ColumnIndex + ")");
if (cell.hasClass("k-dirty-cell")) {
cell.removeClass("k-dirty-cell");
console.log("removed dirty class");
}
}
pendingChanges.length = 0;
// No good, we loose current cell again! (sigh..)
//grid.refresh();
When this didn't work, I also tried resetting the data source dirty flag..
// clear dirty flag from the database
var dirtyRows = $.grep(vm.gridData.view(),
function (item) {
return item.dirty == true;
})
if (dirtyRows && dirtyRows.length > 0) {
dirtyRows[0].dirty = false;
}
demo here
After none of the above worked, I tried the grid.refresh(), but this has the same problem as the datasource sync (we loose our current cell)
Would anyone have any idea how I can clear this cell indicator, without refreshing the whole grid that seems to totally loose our editing context?
Thanks in advance for any help!
Css :
.k-dirty-clear {
border-width:0;
}
Grid edit event :
edit: function(e) {
$("#grid .k-dirty").addClass("k-dirty-clear"); //Clear indicators
$("#grid .k-dirty").removeClass("k-dirty-clear"); //Show indicators
}
http://jsbin.com/celajewuwe/2/edit
Simple solution for resolve that problem is to override the color of the "flag" to transparent.
just override the ".k-dirty" class (border-color)
just adding the above lines to your css
CSS:
//k-dirty is the class that kendo grid use for mark edited cells that not saved yet.
//we override that class cause we do not want the red flag
.k-dirty {
border-color:transparent transparent transparent transparent;
}
This can also be done by applying the below style,
<style>
.k-dirty{
display: none;
}
</style>

Kendo Data Grid "Add new Record" ignores validation rules

I have a DataGrid component with remote CRUD operations.
I have a problem with the validation of its grid fields.
When I click "Add new Record", a new empty line is added to the datagrid.
Without filling in any values, and clicking on "Save Changes" button, the create operation is processed even if no required values are filled.
For example name:
name: {
editable: true,
nullable: false,
validation: {
required: {
message: "Please enter a First name"
}
}
},
Validation Message is displayed only when I click into the name cell.
Is there any way to solve this issue?
I tried enable/ disable batch editing, etc... but without luck.
I recently bumped into this issue as well, it gave me plenty of head scratching, but there are two options.
Use inline editing
Force validation on new cells
I did not go with option 1 for numerous reasons including the fact that you now need to have an edit, update, and cancel button per row before it would do any validation.
Option 2
Got the idea from Brian Roth # the Telerik forums, see here. I used his solution but optimized it a little bit.
In the saveChanges event, implement this:
saveChanges: function (e) {
if (!checkCells(this)) {
e.preventDefault(); //prevents save if validation fails
}
}
checkForInvalidCells will basically go through every new row's cells, open for edit and attempt to close (and in the process, firing the validation). If validation was not successful, then prevent the save.
function checkCells(grid)
{
var rows = grid.tbody.find("tr"); //get rows
for (var i = 0; i < rows.length; i++) {
var rowModel = grid.dataItem(rows[i]); //get row data
if (rowModel && rowModel.isNew()) {
var colCells = $(rows[i]).find("td"); //get cells
for (var j = 0; j < colCells.length; j++) {
if ($(colCells[j]).hasClass('k-group-cell'))
continue; //grouping enabled will add extra td columns that aren't actual columns
grid.editCell($(colCells[j])); //open for edit
if (!grid.editable.end()) { //trigger validation
return false; //if fail, return false
}
else {
grid.closeCell(); //if success, keep checking
}
}
}
}
return true; //all cells are valid
}
In case you are comparing my implementation and his, the difference is:
Made it cleaner without the need for break statement and bool flag
Kept save event variable e logic in the event itself
Utilized isNew() method to check for a new row, a new row's ID/Key may not always be 0, especially if it is an editable field and you have already put info in that field
I account for grouping enabled, grouping will introduce extra td columns that shouldn't be checked for saving
Overall, I hate doing hacks like this, but sometimes it's what you gotta do. Be aware that if you are adding a LOT of new rows at a time, the check will take substantially longer.
Also, each check will move the grid's scroll view to the cell that was last checked (since you are opening the cells for editing, programmatically). If all your new rows are visible at the top of the grid, this is no problem for you, but if you are appending new rows at the bottom, the user may find it strange that the grid has scrolled after saving.
This was a huge help. Thank you very much, #gitsitgo.
I needed to make minor changes to get this to work in my grid, so I thought I'd post it here.
var checkCells = (grid: any): boolean => {
var rows = grid.tbody.find("tr"); //get rows
for (var i = 0; i < rows.length; i++) {
var rowModel = grid.dataItem(rows[i]); //get row data
if (rowModel && rowModel.isNew() || rowModel.IsUpdated) {
var colCells = $(rows[i]).find("td"); //get cells
for (var j = 0; j < colCells.length; j++) {
if ($(colCells[j]).hasClass('k-group-cell'))
continue; //grouping enabled will add extra td columns that aren't actual columns
if ($(colCells[j]).hasClass('k-hierarchy-cell'))
continue; //hierarchy cell is not actual column
grid.editCell($(colCells[j])); //open for edit
if (grid.editable) { //check if editable
if (!grid.editable.end()) { //trigger validation
return false; //if fail, return false
}
else {
grid.closeCell(); //if success, keep checking
}
}
}
}
}
return true; //all cells are valid
}
The differences are:
Checks grid.editable is not null before calling grid.editable.end(). This was the main change that I needed as I have cells that are not editable.
Runs validation for both new and updated rows. Note that IsNew() is a function whereas IsUpdated is a boolean.
Skips cells with class k-hierarchy-cell. This is only needed in hierarchical grids (which is what I'm using this for).

Set page size on client side telerik grid

I have tried a lot but didn't find the way to change page size of telerik grid on client side
Till now I have this on my grid
.Pageable(pager => pager.PageSize(25, new int[] { 25, 50, 100 })
.Style(GridPagerStyles.NextPreviousAndNumeric | GridPagerStyles.PageSizeDropDown))
It works fine but I want to bind page change event with one of my dropdowns.
I didn't find any event that telerik grid's page dropdown call that I can use to call with my dropdown change.
Is it possible to achieve this?
Found the way to do this
function pageSizeChanged(pageSize) {
if (pageSize == '#')
return true;
var grid = $('#StudentGrid').data('tGrid');
grid.pageSize = pageSize;
grid.rebind();
}
This works like a charm! :)

Kendo - Grid - Remove Multiple Rows

I have the following code that remove rows that are checked (each row has a checkbox and I have a Filter button (and other buttons) in the toolbar).
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function(index) {
grid.removeRow($(this));
});
However, performance starts to become an issue when there are > 20 rows being removed. However, kendo filters (removes) 20 rows or more much faster. How is kendo filtering removing multiple rows from the view? Or is there some other better way to remove multiple rows from the grid? Thanks in advance for your help.
** Updated Fiddle to new location - Same code as before **
Try dealing with the data directly. Have the checkbox hooked to the row's Id and filter on that.
I linked a fiddle that removes array elements and then re-creates the grid. The 2 text boxes at the top of the grid capture the range of Ids that you want to remove (this would be the same array of your checkboxIds). Then I cycled through those "remove Ids", removed them from the data array and remade the grid.
I slightly modified a previous fiddle and that's why I'm re-creating the grid instead of dealing with the DataSource object directly. But I hope you get the gist of what I'm doing.
I have 1000 records in this example (only 3 columns) but it removes 950 records very quickly.
Fiddle- Remove from data array
Let me know if you need an example of this with the KendoUI DataSource object.
I included this code below because StackOverflow wouldn't let me post without it.
function filterData() {
var val1 = $("#val1").val();
var val2 = $("#val2").val();
var removeIndexes = new Array();
for (var i = val1; i <= val2; i++) {
removeIndexes.push(i);
}
$(removeIndexes).each(function(removeIndex) {
var removeItemId = this;
$(randomData).each(function(dataIndex) {
var continueLoop = true;
if (this.Id == removeItemId) {
randomData.splice(dataIndex, 1);
continueLoop = false;
}
return continueLoop;
});
});
createGrid();
}
You should use batch updates:
$("#resultsGrid").kendoGrid({
dataSource: {
batch: true,
...
}, ...});
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function() {
var dataItem = grid.dataItem(this);
grid.dataSource.remove(dataItem);
});
grid.dataSource.sync(); // this applies batched changes

Resources