SharpShooter Reports.WPF: Path

SharpShooter Reports.WPF

Path

For simple scenarios, it is not difficult to find an expression for the marker that would address the required highlight criteria.  But it becomes harder to do for more complex cases. For example, if we have a few DataBands in the document, then the expression dataBand.LineNumber will not be applicable, as it will be the same for the rows from multiple tables. In case this DataBand is located in SubReport (what is more, the same template can be used in several SubReports of a single report), and we are required to highlight not only the table row pointed by the cursor, but the column, then finding such expression becomes problematic.

The concept of a full path to an element has been introduced for processing such cases. The path to the element consists of a list of elements, starting and ending both with the document element itself. Thus, type parameter is specified for all the elements, while the number of iteration is additionally specified for iterative elements (such as DataBand and CrossBand).

In general, the full path has the following structure:

<element>|<element>|…|<element>

And the element structure is as follows:

<element type>:<element name> - for non-iterative elements

<element type>:<element name>[<iteration number>] – for iterative elements

For example, , the full path will have the following structure for an element located in SubReport at the intersection of DataBand and CrossBand elements (considering the fact that SubReport itself is placed inside DataBand):

Document:document1|Page:page1|DataBand:dataBand1[1]|SubReport:subReport1|Document:document1|Page:page1|DataBand:dataBand1[5]|Detail:detail1|CrossBand:crossBand1[0]|TextBox:textBox7

Note that the element for which the path is generated is the last element in the path structure. Its direct parent is the second element from the end, and so on up to the first element which is always represented as a document element.

In order to set the element path as a marker, it is necessary to set the Marker binding value for the element using the “Path” expression. Global “Path” variable gets the full path to the currently generated element.

As you can see, despite the fact that the path structure contains duplicate names, we can uniquely determine the position of the element in the generated report. But as it happens with any universal solutions, getting the required information from the path value is not an easy task. That’s why a special helper to perform typical path comparison operations was introduced.

For a start we need to create it. Note that the helper caches paths under comparison, thus, it allows the increase of performance since one and the same path is not parsed multiple times. So, the most efficient way is to declare the helper once and allow it to use cached data for the next references to it. It’s worth mentioning that when a report with the other structure is opened, the helper should be recreated to release memory and increase performance due to less cached elements to be processed.

private PathComparer pathComparer = new PathComparer();

The helper has the following methods for paths comparison:

  • public bool SameCrossBandLine(string path1, string path2)

    Compares two paths for match of iteration number of the СrossBand containing the element with the specified path. If the CrossBand is unavailable in both cases, it returns TRUE.

  • public bool SameDataBandLine(string path1, string path2)

    Checks if both paths belong to one and the same string of one and the same DataBand line. In case the DataBand is nested in the other DataBand the method will return TRUE for the elements that belong to strings with equal index of the nested DataBand for all strings of the master DataBand. If the DataBand is unavailable in both paths, the method will return TRUE.

  • public bool SameDataBandLine(string path1, string path2, int level)

    Checks that both paths belong to one and the same string of one and the same DataBand under level index starting from the nearest one to the element. Zero based index. In case the DataBand is nested in the other DataBand, the method will return TRUE for all strings with equal index of the nested DataBand for all string of the master DataBand. If DataBand is unavailable in both paths, the method will return TRUE.

  • public bool SameDataBandLineHierarchy(string path1, string path2)

    Checks if both paths belong to the equal strings of the equal DataBands.

  • public bool SameElement(string path1, string path2)

    Returns TRUE if both paths are generated by one and the same element. Path match is not checked in this case, i.e. the elements may belong to different strings of the DataBand, etc. The method can be used to determine columns of the table that doesn’t use CrossBand to generate columns.

  • public bool SameParent(string path1, string path2)

    Returns TRUE if the elements for which the specified paths are generated have one and the same direct parent. Path match is not checked in this case, i.e. the elements may belong to different DataBand strings, etc.

  • public bool SameParent(string path1, string path2, int level)

    Returns TRUE if the elements for which the specified paths are generated have one and the same parent under the level index starting from the direct parent. Zero based index. Path match is not checked, i.e. the elements may belong to different DataBand strings, etc.

  • public bool SameParents(string path1, string path2)

    Checks if both elements have the parent with equal full path.

  • public bool SamePage(string path1, string path2)

    Returns TRUE if both elements belong to one and the same page of one and the same template. Full page path is checked, thus, if the page belongs to SubReport iterated via DataBand, the pages that belong to different strings of the DataBand are considered different.

Note that to process paths, PathComparer parses them first; it results in additional overhead. Even when all values are parsed and cached, comparison with PathComparer will work slower than the direct comparison of strings for match. That is why it’s recommended, if possible, to use Marker value different from Path and PathComparer that will allow you to highlight necessary areas with simple comparison for path match. It’s necessary to take into account that more complicated scenarios of strings processing work much slower.

Example. Use Path mechanism to highlight the line when mouse hovers over. The cell is highlighted by other color.

private PathComparer pathComparer = new PathComparer();
 
void reportViewer_ElementHover(object sender, ReportElementMouseEventArgs e)
{
    if (string.IsNullOrEmpty(e.ElementMarker))
    {
        // No elements under the cursor.
        reportViewer.ResetHighlight();
    }
    else
    {
        reportViewer.HighlightControls(x =>
            e.ElementMarker == x
                ? System.Windows.Media.Brushes.DarkGray
                : pathComparer.SameDataBandLineHierarchy(e.ElementMarker, x)
                    || pathComparer.SameElement(e.ElementMarker, x)
                        ? System.Windows.Media.Brushes.Gray
                        : null);
    }
}


Add Feedback