Author Archives: Yuriy

WHDG: Correctly detect Async Callback

When using Infragistics WebHierarchicalDataGrid often there’s a need to detect grid’s async callback (for example we need to rebind the grid if it performs AJAX paging or expanding children). For flat WebDataGrid it was suggested to use grid’s RunBot.IsCallback property:

If xMyGrid.RunBot.IsCallback Then
   'Perform some operations for grid's async callback
End If

Now, WHDG also has RunBot.IsCallback property, but the above code always returns False for it. I know I’ve seen this before – a situation where a property doesn’t work on WHDG control itself, but works on the WHDG’s GridView object. Sensing a pattern I modified the code above for WHDG:

If xMyGrid.GridView.RunBot.IsCallback Then
   'Perform some operations for grid's async callback
End If

And bingo! Now Async callback is detected correctly.


UPDATE 4/27/2012: Turned out the above method doesn’t always work either. (To Infragistics stuff, if anybody happened to read this: The scenario above happens with WHDG in manual load on demand mode when grid’s RowIslandPopulating event is handled and ContainerGrid is created on demand and bound to data retrieved from the Database). The above method works when rows of the top level expanded (xMyGrid.GridView.RunBot.IsCallback is True) but fails if child rows are expanded to show grandchildren (in that case xMyGrid.GridView.RunBot.IsCallback is False).

We need another more reliable way to detect callback, no matter what caused it. And we can do that by checking HTTP Request. If it’s an Infragistics callback it will have a Form parameter with key like "__IGCallback************". So the code to always detect the callback correctly is:

If Request.Form.AllKeys.Any(Function(S As String) S IsNot Nothing AndAlso S.StartsWith("__IGCallback")) Then
   'Perform some operations for grid's async callback
End If

WebDataTree returns multiple selected nodes in single-select mode

This could be a bug in Infragistics WebDataTree control or it could be a very specific scenario (maybe it’s even by design, I don’t know) but here’s a weird behavior that I encountered. Using following code in WebDataTree’s event handler (oh and by the way, tree control is in a single-select mode):

Protected Sub xMyTree_SelectionChanged(ByVal sender As Object, ByVal e As NavigationControls.DataTreeSelectionEventArgs) Handles MyTree.SelectionChanged
   if e.NewSelectedNodes(0).Text = "Some Value"
      'do something with newly selected tree node
   end if
End Sub

I intended to use newly selected node to perform some operations. To my surprise e.NewSelectedNodes(0) referred to previously selected node (despite the name of the property) and newly selected value were located in e.NewSelectedNodes(1)! So the quick workaround was to use slightly modified code:

Protected Sub xMyTree_SelectionChanged(ByVal sender As Object, ByVal e As NavigationControls.DataTreeSelectionEventArgs) Handles MyTree.SelectionChanged
   if e.NewSelectedNodes(e.NewSelectedNodes.Count-1).Text = "Some Value"
      'do something with newly selected tree node
   end if
End Sub

This way it will always get latest selected node and the solution is universal. If the bug described above occurs – code will grab e.NewSelectedNodes(1) (because Count = 2). If the tree behaves as expected – code will get grab e.NewSelectedNodes(0) (because Count = 1)

iOS is ported to Kindle Fire!

Apple iOS running on Amazon Kindle Fire
Those coding wizards from XDJ-Developers have done it again! After years of supplying us with huge amounts of amazing custom ROMs for even huger amount of Android devices they performed yet another miracle which is akin to splitting the atom, since it separates what was formerly considered inseparable: Apple hardware and software.

They ported iOS to Kindle Fire.

Don’t expect it to be the latest version though (iOS 6 as of time of this post) for that you will have to wait couple hours. For now be content with 5.1 – it’s well worth it. iOS 5.1 runs very smoothly on Kindle Fire, in tests pretty much everything lives up to high standards we used to expect from Apple, just about only app that wouldn’t run is Fruit Slice, I can’t imagine why.

Being an early beta build, it still has a few quirks. For example sometimes, if you launch iTunes, you end up in Amazon MP3 Store and on very rare occasions in some place called “Tower Records” (must be phantom growing pains) but XDJ-Developers are hard at work to eradicate those.

So rejoice closet Apple fans! No longer you have to pretend to like cupcakes, donuts, eclairs, froyo, gingerbread, honeycombs, ice cream sandwiches and the rest of those high calory desserts. Time for a healthy diet of fruit!

Solution for WebHierarchicalDataGrid “DataKeyField is invalid” error

If you’re using Infragistics WebHierarchicalDataGrid and getting “DataKeyField is invalid” error after assigning DataKeyFields property for the root level:

xMyGrid.DataKeyFields = "[Key 1],[Key 2],[Key 3]"

and trying some data manipulation (like deleting rows, binding data etc.), try using GridView property of the grid instead:

xMyGrid.GridView.DataKeyFields = "[Key 1],[Key 2],[Key 3]"

The first method used to work, but somewhere around 2011 release of NetAdvantage it broke.

Partially hide external content with CSS overflow

If you ever hosted a content from external website in an IFRAME on your own site and wanted, for no reason whatsoever, to hide either top, bottom, left or right portion of that content – there’s an easy way.

Imaginge you have HTML markup like this:

<iframe frameborder="no" width="275" height="95" src="https://www.google.com/images/srpr/logo3w.png" />

It will display a pretty logo of some 3rd party company:

Now you got an idea to improve it a bit, by removing unneeded characters. Take a look at following markup:

<div style="width:275px;overflow:hidden">
   <div style="margin:0px 0px 0px -120px">
      <iframe frameborder="no" width="275" height="95"
      src="https://www.google.com/images/srpr/logo3w.png" />
   </div>
</div>

Our IFRAME is now enclosed into 2 DIVs. Internal one shifts left margin of its content 120px into the content, and external one effectively hides everything outside the margins via hidden overflow. The result:

Of course the content doesn’t have to be IFRAME with external content, but if it’s internal to your site that means you have full control over it and don’t need to use this hack.

Remove namespaces from Xpath expression

If you ever need to remove namespaces from an XPath string, regex is a way to go. [\w]+:(?!:) expression to be precise. So if, for example your xpath is

Dim sXpath as String = "/ns1:ElementOne/ElementTwo/ns2:ElementThree"

this code

Regex.Replace(sXpath, "[\w]+:(?!:)", "")

will convert it into

/ElementOne/ElementTwo/ElementThree

Thanks Bogdan Emil Mariesan @ Stack Overflow for the solution

Totally custom filter for UltraWebGrid using LINQ

Last time I described how LINQ can be used to custom filter ADO.NET DataTable. This time I will demonstrate how this technique can replace built-in server-side filtering in Infragistics UltraWebGrid.

By default if server-side filtering is enabled in UltraWebGrid controls, it displays a small “funnel” icon in the column header, if you click this icon – a list of unique values from this column is displayed and selecting a value filters the grid by displaying only rows that have this value.

This default behavior works, sort of – it has many issues. If your grid has paging enabled – only values from the current page will be displayed. If your columns or values has characters that grid doesn’t like (commas, square brackets etc.) an exception will be thrown (this happens because under the hood grid converts your filters into a string that is passed to DataTable’s RowFilter), there’re other issues as well.

Why leave anything to chance when you can provide filtering yourself? Continue reading →

Replace DataTable RowFilter with LINQ

ADO.NET DataTable offers handy RowFilter property (via its DefaultView object), for example to filter by some string value and display filtered data in a grid a code like this is used:

odtMyData.DefaultView.RowFilter = "Field = 'value'"
odgDataGrid.DataSource = odtMyData
odgDataGrid.DataBind()

where odtMyData is a DataTable object and odgDataGrid is a Data Grid.

This works well, but what if you need preprocess data in the DataTable prior comparing it to the filter value – what if you need to apply a user-defined function to it? In my case I had a VB function called ProcessTags which stripped HTML tags from a string, so for example strings like this:

<a href="http://someurl">This is a sample text</a>

and this

<span style="color:red">This is a </span><label>sample text</label>

would be converted into the same text

This is a sample text

So I needed to create condition that would return DataTable rows with that have both HTML values by comparing to "This is a sample text".

How? RowFilter‘s syntax is pretty poor and external function cannot be used, so something like

odtMyData.DefaultView.RowFilter = "ProcessTags(Field) = 'This is a sample text'"
odgDataGrid.DataSource = odtMyData
odgDataGrid.DataBind()

would throw an error.
Continue reading →

Absolute coordinates of element inside of IFRAME

Often there’s a need to determine absolute coordinates of an HTML element within a page, for example you need to display a popup menu on a button click at the button coordinates. Code for this is well known, here is one of the variations:

// Define class that will hold Object coordinates
function CTopLeft(i_nTop, i_nLeft) {
   this.nTop = i_nTop;
   this.nLeft = i_nLeft;
}

// Get Top, Left coordinates of a DOM element
function GetTopLeft(i_oElem) {
   var cTL = new CTopLeft(0, 0);
   var oElem = i_oElem;
 
   do {
      cTL.nLeft += oElem.offsetLeft;
      cTL.nTop += oElem.offsetTop;
      oElem = oElem.offsetParent;
   } while (oElem)
   
   return cTL;
}

This code is pretty straightforward: we’re looping thru all element’s ancestors, adding up each parent’s offsetTop and offsetLeft to get actual element coordinates.

This works well when your page is at the top level. But what if the page is inside of an IFRAME? Then the code above would give you coordinates of an element within the IFRAME window only. But what if you still need absolute coordinates of the element within browser window? Taking the example above – you need to display popup menu on the button clicked inside of IFRAME, but the menu can grow big and go outside of IFRAME boundaries. So the menu element need to be hosted outside of the IFRAME and coordinates need to be absolute withing browser window.

Let’s throw IFRAMEs into the mix: Continue reading →

Speed up UltraWebGrid with direct DOM access

Infragistics UltraWebGrid offers rich client-side programming model, but often it can be extremally slow. As an example consider a simple task: Given a particular Row ID hide the rest of the grid rows, keeping only this row visible.

Using UltraWebGrid’s CSOM (Client Side Object Model) JavaScript code looks like this:

var oGrid = igtbl_getGridById('xMyGrid');    // Get reference to grid object

for (var sRowID in oGrid.Rows) {   // Looping thru all rows in grid's rows collection

   if (sRowID != sSelectedRowID) {   // If current row ID is not given ID
      igtbl_getRowById(sRowID).setHidden(true) // Get reference to row and hide it
   }

}

The code works – it really does. But to loop thru 50 rows in this manner can take 10-15 seconds, not something your user will be happy about when instant action is expected. Continue reading →