Infragistics UltraGrid Group Changed Event - events

I have an Infragistics UltraGrid and I need to know when the user adds/removes a column grouping. I see there are events for when a row is collapsed/expanded and an event for when the grid's filter changes, but I don't see any events that would fire when a column grouping is added/removed. Does anyone know of an UltraGrid event that would fire at that point? If not, are there any workarounds I might be able to use to achieve this?
I've already tried using AfterBandHiddenChanged and AfterGroupPosChanged. Neither of those seem to do what I need.
I'm using Infragistics 11.2 CLR2.0 (I know it's quite out-of-date, but it's not my call to update it)

After some digging and experimenting, I found a workaround. It's not the prettiest, but it gets the job done. If anyone has any better suggestions, I'm all ears. But here's what I came up with in case someone else is interested.
I utilize the grid's BeforeSortChanged and AfterSortChanged events. The "Before" event sets a flag to indicate whether the groupings have changed. The "After" event is where I perform the operation I need to perform if the flag was set to indicate that the groupings changed.
Here's the "Before" event:
private void Grid_BeforeSortChange(object sender, Infragistics.Win.UltraWinGrid.BeforeSortChangeEventArgs e) {
int preSort = 0;
int postSort = 0;
// This set of sorted columns are the columns that were already sorted
// before the sort change.
foreach (var col in e.Band.SortedColumns) {
if (col.IsGroupByColumn) {
preSort++;
}
}
// This set of sorted columns are the columns that will be
// sorted after the sort change is applied
foreach (var col in e.SortedColumns) {
if (col.IsGroupByColumn) {
postSort++;
}
}
// Compare the number of grouped columns before the
// sort to the number after the sort
_groupingsChangedFlag = preSort != postSort
}
And here's the "After" event:
private void Grid_AfterSortChange(object sender, Infragistics.Win.UltraWinGrid.BandEventArgs e) {
if (!_groupingsChangedFlag) {
return;
}
// Groupings changed, so do some action
}

Related

How to count total Local Data rows for Data Driven testing and then perform a function on a particular row?

I'm writing test automation scripts that is based on Data Driven testing for Web Browser test. I'm using Local Data as my data source.
Eg: Local Data table contains 2 rows and 2 columns for Username and Password.
I'm wondering is there is a way to perform a row "Count" function for the Local Data table.
And then,if the row count is two, perform a specific function.
The idea is something like this :
if LocalData.Row = 2 then
//Execute a function
else
//Close Browser
I can't seem to find any resources in the net for this. I'm just being introduced to Telerik so i'm learning as it goes and i'm really hoping you guys can help to give some pointers on this question.
Many many thanks in advance :)
Column and row are two different things.
When accessing the column by the RAD_Grid.MasterTableView.Columns.
You will be able to modify all the properties of a column. Like :
FilterDelay, CurrentFilterFunction, ShowFilterIcon, DataField, UniqueName, Display, Exportable...
foreach (GridColumn column in RAD_Grid.MasterTableView.Columns)
{
if (column is GridBoundColumn)
{
GridBoundColumn boundColumn = column as GridBoundColumn;
boundColumn.CurrentFilterValue = string.Empty;
}
}
To iterate through the row, on the data bound:
protected void Unnamed_DataBound(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem item = (GridDataItem)e.Item;
// LOGIC
}
//Total Item Count:
if (e.Item is GridPagerItem)
{
int itemsCount = ((GridPagerItem)e.Item).Paging.DataSourceCount;
}
}
Or
GridItemCollection gridRows = RAD_Grid.Items;
int i;
foreach (GridDataItem data in gridRows)
{
i++;
ItemClass obj = (ItemClass)data.DataItem;
}
As its not really clear what you want I will give you an other way around.
In your grid put a templated Column. I' am pretty sure that's what you are looking for. And if the logic is complexe put it in a function in code behind and simply :
<asp:Label ID="lbl_Exmpl" runat="server"
Text=' <%# MyFunction( Convert.ToInt32(Eval("Mydata")) ) %>' />

How to reorder columns in datatable with drag and drop Primefaces

I use primefaces version 5.2 and jsf version 2.2.6.
I have a datatable and I want to reorder the columns with drag and drop. Besides I have also the column toggle functionality, with which I can hide columns. The reordering and hiding of columns are saved into the database.
For me it is no problem if on specific positions are hidden columns, I can drop the dragged column after or before the position of the hidden ones.
I use the following ajax event:
<p:ajax event="colReorder" listener="#{transactionsPage.onColumnReorder}"/>
and the method signature looks like this:
public void onColumnReorder(AjaxBehaviorEvent event)
If I could have used ReorderEvent to get the fromIndex and toIndex, it would have been very easy to deal with this situation, but unfortunately this event can be used only for dragging and dropping rows and not columns.
Is there a way to find out these indexes? Even only the fromIndex could be enough.
I managed to find a solution, maybe it can be helpful for someone in the future.
Because I didn't find indexes for fromIndex and toIndex for reordering the columns(there are only such indexes for reordering rows, which work with the ReorderEvent), I get the datatable from the AjaxBehaviorEvent and from that I get the columns and overwrite these indexes of the reordered columns in the database columns and then I can restore the view later with the reordered columns.
The code for triggering the event from the xhtml page looks like this:
<p:ajax event="colReorder" listener="#{transactionsPage.onColumnReorder}"/>
The code for the managed bean looks like this:
public void onColumnReorder(AjaxBehaviorEvent event) {
DataTable table = (DataTable) event.getSource();
List<ViewAttributes> allViewAttributesList = loadAllViewAttributes();
for (int i = 0; i < table.getColumns().size(); i++) {
UIComponent colComponentDestination = (UIComponent) table.getColumns().get(i);
//allViewAttributes is the list of columns from the database, in which I set the new indexes
for (int j = 0; j < allViewAttributesList.size(); j++) {
ViewAttributes viewAttrSource = allViewAttributesList.get(j);
if (viewAttrSource.getColumnName().equals(colComponentDestination.getId()) && i != viewAttrSource.getPosition()) {
viewAttrSource.setPosition(new Long(i));
//save column with new index in the database
getServiceManager().getViewService().getViewDao().update(viewAttrSource);
}
}
}
}

My CellTable does not sort

I red a lot about sorting a CellTable. I also went trough the ColumnSorting with AsyncDataProvider. But my CellTable does not sort.
Here is my code:
public class EventTable extends CellTable<Event> {
public EventTable() {
EventsDataProvider dataProvider = new EventsDataProvider(this);
dataProvider.addDataDisplay(this);
SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 5, true);
pager.setDisplay(this);
[...]
TextColumn<Event> nameCol = new TextColumn<Event>() {
#Override
public String getValue(Event event) {
return event.getName();
}
};
nameCol.setSortable(true);
AsyncHandler columnSortHandler = new AsyncHandler(this);
addColumnSortHandler(columnSortHandler);
addColumn(nameCol, "Name");
getColumnSortList().push(endCol);
}
}
public class EventsDataProvider extends AsyncDataProvider<Event> {
private final EventTable eventTable;
public EventsDataProvider(EventTable eventTable) {
this.eventTable = eventTable;
}
#Override
protected void onRangeChanged(HasData<Event> display) {
int start = display.getVisibleRange().getStart();
int length = display.getVisibleRange().getLength();
// check false values
if (start < 0 || length < 0) return;
// check Cache before making a rpc
if (pageCached(start, length)) return;
// get Events async
getEvents(start, length);
}
}
I do now know, if all the methods are need here. If so, I will add them. But in short:
pageCached calls a method in my PageCache Class which holds a map and a list. Before making a rpc call, the cache is checked if the events where already taken and then displayed.
getEvents just makes an rpc call via asynccallback which updates the rowdata via updateRowData() on success.
My Table is displayed fast with currently around 500 entries (could be more, depends on the customer). No missing data and the paging works fine.
I just cannot get the sorting work. As far as I know, AsyncHandler will fire a setVisibleRangeAndClearData() and then an onRangeChanged(). onRangeChanged is never fired. As for the setVisibleRangeAndClearData() I do not know. But the sortindicator (arrow next to the columnname) does change on every click.
I do not want to let the server sort the list. I have my own Comparators. It is enough, if the current visible page of the table is sorted. I do now want to sort the whole list.
Edit:
I changed following code in the EventTable constructor:
public EventTable() {
[...]
addColumnSortHandler(new ColumnSortEvent.AsyncHandler(this) {
public void onColumnSort(ColumnSortEvent event) {
super.onColumnSort(event);
MyTextColumn<Event> myTextColumn;
if (event.getColumn() instanceof MyTextColumn) {
// Compiler Warning here: Safetytype unchecked cast
myTextColumn = (MyTextColumn<Event>) event.getColumn();
MyLogger.log(this.getClass().getName(), "asc " + event.isSortAscending() + " " + myTextColumn.getName(), Level.INFO);
}
List<Event> list = dataProvider.getCurrentEventList();
if (list == null) return;
if (event.isSortAscending()) Collections.sort(list, EventsComparator.getComparator(EventsComparator.NAME_SORT));
else Collections.sort(list, EventsComparator.descending(EventsComparator.getComparator(EventsComparator.NAME_SORT)));
}
});
addColumn(nameCol, "Name");
getColumnSortList().push(endCol);
}
I had to write my own TextColumn to determine the Name of the column. Otherwise how should I know, which column was clicked? The page gets sorted now but I have to click twice on the column. After then, the sorting is done with every click but in the wrong order.
This solution does need polishing and it seems kinda hacky to me. Any better ideas?
The tutorial, that you linked to, states:
This sorting code is here so the example works. In practice, you would
sort on the server.
Async provider is used to display data that is too big to be loaded in a single call. When a user clicks on any column to sort it, there is simply not enough objects on the client side to display "first 20 evens by name" or whatever sorting was applied. You have to go back to your server and request these first 20 events sorted by name in ascending order. And when a user reverses sorting, you have to go to the server again to get first 20 events sorted by name in a descending order, etc.
If you can load all data in a single call, then you can use regular DataProvider, and all sorting can happen on the client side.
EDIT:
The problem in the posted code was in the constructor of EventsDataProvider. Now it calls onRangeChanged, and the app can load a new sorted list of events from the server.

ASPxGridView Group Summary Sorting - It sorts the content inside, not the summary outside

I have done grouping of the grid by giving groupindex to a particular column in aspxgridview.
For example, if I am grouping by means of persons name and the orders details made by that particular person would come in the detailed content when the arrow is clicked to view the content.
When I click on the header fields to sort, it is sorting the data inside the groupContent but it is not used for sorting the data of groupsummary
I am showing all the totals as a part of group summary besides the person's name.
For example if you see in the below link:
https://demos.devexpress.com/ASPxGridViewDemos/Summary/GroupSortBySummary.aspx
If you sort by company name, the content would be sorted, but the summary showing the country and sum has no means to get sorted at outside level.
Please do suggest me options to work out this problem.
Thanks.
Here is workaround, based on this example.
The main idea is to create summary item which shows the minimum or maximum value of Country column inside City group and sort City group by this summary values. For this BeforeColumnSortingGrouping event is used to change the sorting behavior.
Here is example:
<dx:ASPxGridView ...
OnBeforeColumnSortingGrouping="gridCustomers_BeforeColumnSortingGrouping">
private void SortByCountry()
{
gridCustomers.GroupSummary.Clear();
gridCustomers.GroupSummarySortInfo.Clear();
var sortOrder = gridCustomers.DataColumns["Country"].SortOrder;
SummaryItemType summaryType = SummaryItemType.None;
switch (sortOrder)
{
case ColumnSortOrder.None:
return;
break;
case ColumnSortOrder.Ascending:
summaryType = SummaryItemType.Min;
break;
case ColumnSortOrder.Descending:
summaryType = SummaryItemType.Max;
break;
}
var groupSummary = new ASPxSummaryItem("Country", summaryType);
gridCustomers.GroupSummary.Add(groupSummary);
var sortInfo = new ASPxGroupSummarySortInfo();
sortInfo.SortOrder = sortOrder;
sortInfo.SummaryItem = groupSummary;
sortInfo.GroupColumn = "City";
gridCustomers.GroupSummarySortInfo.AddRange(sortInfo);
}
protected void Page_Load(object sender, EventArgs e)
{
SortByCountry();
}
protected void gridCustomers_BeforeColumnSortingGrouping(object sender, ASPxGridViewBeforeColumnGroupingSortingEventArgs e)
{
SortByCountry();
}
When you group by a column devexpress automatically uses that column to sort. Without sorting the data the grouping is not possible. To overcome this issue we have sorted the datasource itself then applied that datasource to the grid.

Using DataObjectTypeName in DataObjectSource

The functionality I am trying to use is:
- Create a ObjectDataSource for selection and updating controls on a web page (User Control).
- Use the DataObjectTypeName to have an object created that would send the data to an UpdateMethod.
- Before the values are populated in the DataObjectTypeName’s object, I would like to pre-populate the object so the unused items in the class are not defaulted to zeros and empty strings without me knowing whether the zero or default string was set by the user or by the application.
I cannot find a way to pre-populate the values (this was an issue back in 2006 with framework 2.0). One might ask “Why would anyone need to pre-populate the object?”. The simple answer is: I want to be able to randomly place controls on different User Controls and not have to be concerned with which UpdateMethod needs to handle which fields of an object.
For Example, let’s say I have a class (that reflects a SQL Table) that includes the fields: FirstName, LastName, Address, City, State, Zip. I may want to give the user the option to change the FirstName and LastName and not even see the Address, City, State, Zip (or vice-versa). I do not want to create two UpdateMethods where one handled FirstName and LastName and the other method handles the other fields. I am working with a Class of some 40+ columns from multiple tables and I may want some fields on one screen and not another and decide later to change those fields from one screen to another (which breaks my UpdateMethods without me knowing).
I hope I explained my issue well enough.
Thanks
This is hardly a solution to the problem, but it's my best stab at it.
I have a GridView with its DataSourceID set to an ObjectDataSource.
Whenever a row is updated, I want the property values in the object to be selectively updated - that is - only updated if they appear as columns in the GridView.
I've created the following extension:
public static class GridViewExtensions
{
public static void EnableLimitUpdateToGridViewColumns(this GridView gridView)
{
_gridView = gridView;
if (_gridView.DataSourceObject != null)
{
((ObjectDataSource)_gridView.DataSourceObject)
.Updating += new ObjectDataSourceMethodEventHandler(objectDataSource_Updating);
}
}
private static GridView _gridView;
private static void objectDataSource_Updating(object sender, ObjectDataSourceMethodEventArgs e)
{
var newObject = ((object)e.InputParameters[0]);
var oldObjects = ((ObjectDataSource)_gridView.DataSourceObject).Select().Cast<object>();
Type type = oldObjects.First().GetType();
object oldObject = null;
foreach (var obj in oldObjects)
{
if (type.GetProperty(_gridView.DataKeyNames.First()).GetValue(obj, null).ToString() ==
type.GetProperty(_gridView.DataKeyNames.First()).GetValue(newObject, null).ToString())
{
oldObject = obj;
break;
}
}
if (oldObject == null) return;
var dynamicColumns = _gridView.Columns.OfType<DynamicField>();
foreach (var property in type.GetProperties())
{
if (dynamicColumns.Where(c => c.DataField == property.Name).Count() == 0)
{
property.SetValue(newObject, property.GetValue(oldObject, null), null);
}
}
}
}
And in the Page_Init event of my page, I apply it to the GridView, like so:
protected void Page_Init()
{
GridView1.EnableLimitUpdateToGridViewColumns();
}
This is working well for me at the moment.
You could probably apply similar logic to other controls, e.g. ListView or DetailsView.
I'm currently scratching my head to think of a way this can be done in a rendering-agnostic manner - i.e. without having to know about the rendering control being used.
I hope this ends up as a normal feature of the GridView or ObjectDataSource control rather than having to hack it.

Resources