XamlQuery Selectors are similar to selectors of CSS (cascading style sheets) and jQuery. The selector symbols and syntax are borrowed from CSS and jQuery. XamlQuery Selectors operate on rendered Silverlight output, where CSS and jQuery selectors operate on rendered HTML output.
What is a Selector?
A Selector is a string that contains a set of matching rules or conditions that determine which controls to extract from the rendered Silverlight output. It is like a pattern or query that contains simple control names to rich / complex patterns.
If all the rules / conditions in the pattern are true for a given control, the selector matches that control. The identifiers (like control names, control types, style names, etc.) in the selector pattern are case sensitive. The controls found by a selector are called as subjects of that selector.
The input query pattern can contain one or more selectors, separated by comma.
selector-1, selector-2, ... ... ... selector-n
A selector is a chain of one or more simple selectors, separated by combinator symbols. Combinator symbols are white-space (descendant selector), '>' (child selector) and '+' (adjacent selector). Additional white-spaces around a combinator symbol are ignored. Note if there are n simple-selectors in a selector, there will be n-1 combinators.
simple-selector-1 combinator-1 simple-selector-2 combinator-2 ... ... ... combinator(n-1) simple-selector-n
A simple-selector is either a type-selector or universal-selector followed immediately by zero or more filter selectors. Immediately implies that there should not be any white-space between a simpleselector and its filter-selectors.
[*]filter-selector-1 filter-selector-2 ... ... ... filter-selector-n
filter-selector-1 filter-selector-2 ... ... ... filter-selector-n
A filter selector is a style-selector or name-selector or property-selector.
The following table summarizes the syntax of selectors.
The universal selector, written as '*', matches any control. It matches any single control in the rendered Silverlight output, including additional controls created dynamically during rendering. The symbol '*' can be omitted, if it is not the only component of a simple-selector.
- *#MainCanvas is equivalent to #MainCanvas
- *.GreenRect is equivalent to .GreenRect
- *[Tag=Highlighted] is equivalent to [Tag=Highlighted]
The type selector finds controls whose type is equal to given type or subclass of given type. It matches every instance of the control type within the search scope.
Type selectors can be used to find controls of specific type or a range of types (represented by a baseclass). For example, Shape will match all controls that are extended from Shape like Rectangle, Line, Ellipse, etc.
The following example finds all textbox controls inside a grid.
The following query finds all rectangles inside a canvas.
The following query finds all Shapes (Rectangle, Line, Ellipse, etc.) inside a canvas.
The following query finds all Selectors (ComboBox, ListBox, etc.) inside a grid.
A descendant selector is made up of two or more selectors separated by white-space. A descendant selector of the form "E F" matches all F controls which are descendants of control E. A descendant means a control that appears as a child (any depth, not immediate child) in the visual tree of rendered Silverlight output. That is, E can be reached by traversing upwards from F, no matter how many iterations in the traversal.
The following example finds all ellipses inside a canvas.
The following example finds all textboxes that are grand child of a scroll viewer. The "*" indicates that a ScrollViewer must be the ancestor of some control and that control must be an ancestor of a TextBox.
ScrollViewer * TextBox
The following example finds all controls whose tag value is equal to 'Highlighted' (irrespective of the control type).
A child selector is made up of two or more selectors separated by ">" symbol. A child selector of the form "E > F" matches all F controls that are children of control E. The control E should be a container control. A container control is a control that is extended from Panel class. Note that a child is a descendant but not all descendants are children. In fact, a child means an immediate descendant.
The following example gets all shapes with style named 'Stroke'.
#MainCanvas > Shape.Stroke
This query is similar to the following, assuming that MainCanvas is a descendant of LayoutRoot.
LayoutRoot #MainCanvas > Shape.Stroke
The following example gets all grids that are immediate children of all stack-panels in the search scope.
StackPanel > Grid
The following example gets all children of a wrap-panel named 'ScoresContainer'.
WrapPanel#ScoresContainer > *
Adjacent selectors have the syntax E1 + E2, where both E1 and E2 are subjects of the selector. The selector matches if both E1 and E2 are children of a same parent. The parent control should be a container control. A container control is a control that is extended from Panel class.
The following query matches all green rectangles and red lines inside a canvas.
#MainCanvas Rectangle.GreenRect + Line.RedLine
A style selector contains a dot (.) immediately followed by the style name. The selector matches all controls whose style is equal to or based on a given style. That is, the style name can be the name of exact required style or name of any base styles (declared with Style.BasedOn property).
The styles can reside in the same XAML file or any merged resource dictionary or Application XAML (App.xaml). XamlQuery will search for styles and base-styles in all these locations.
The following query finds all controls with style 'GrayText', irrespective of control type.
The following query finds all ellipses of style named 'HighlightedNode'.
The following query finds all ellipses of style named 'MapNode'.
If 'HighlightedNode' style is based on 'MapNode' style, then this query will match highlighted nodes also.
A name selector contains a hash (#) immediately followed by the control name. The selector finds the control with the given name.
Only one control can exist with a given name in current namescope. Certain features of Silverlight such as templates or calls to APIs such as XamlReader.Load method can define separate XAML namescopes, which leads to two controls under the same name. However, there can be only one control in a given namescope. The name-selector finds and returns one control whose name is equal to given name in the current namescope. The current namescope means namescope of reference control passed to Search() method of XamlQuery.
The following query finds the control named 'RegisterGrid'.
The following example finds the control named 'EmailTextBox' that is a descendant of 'RegisterGrid'.
The property selectors are used to choose a set of controls based on the value of a given property. The property selectors can be applied to both normal properties (regular properties of a class) and dependency properties.
The dependency property names should contain the name of the defining class delimited by an underscore. Some examples are Canvas_Left, Grid_Row, FrameworkElement_Visibility, etc. The property names need not to end with 'Property'. That is, FrameworkElement.VisibilityProperty should be given as FrameworkElement_Visibility.
Matches if the property is set i.e. the value is not equal to default property value. For reference properties, the default value will be null and for value properties (like int) the default value will be a constant.
For example, the following query will get all text-boxes whose Tag property is set.
This query is equivalent to the following
Matches if the property value is exactly equal to the given value. Equals() method of object is used to check the equality.
The following query will get all text-blocks in second column of a grid.
The following query will get the textbox whose tag value is 'Current'.
The following example gets all lines whose stroke-thickness is 2.
Matches if the property value is not equal to the given value. Equals() method of object is used to check the equality.
The following query will get all shapes that are not opaque.
The following query will get all shapes with some height.
Matches if the property value starts with the given value.
The following example will find all controls whose name starts with 'Rect'.
Matches if the property value ends with the given value.
The following query gets all controls whose name ends with 'TextBox'.
Matches if the property value contains the given value.
The following query gets all controls whose tag property contains the text 'Red'.
The starts-with (^), ends-with ($) and contains (~) symbols are ideal for string properties only (like Name, Tag, etc.), because string-representation of the property value will be used for matching. The string-representation is get by ToString() method of object class.