Jump to: navigation, search

Difference between revisions of "Property Based Content Filters"


m
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
A collection of property-based content filtering criteria can be applied to child object lists. {{Version/WinXSince|2.6.1}} Some common use cases are as follows.
+
{{Version/WinXSince|2.6.1}} The UI can be customized to accept user inputs as filter criteria, and reduce the entire child list to a sub-list based on property values that contain that text. Each filter is 'attached' to a single metaproperty, and multiple filters can be applied at once.
* A user can enter a text to reduce the entire child list to a sub list of those whose certain property display values contain that text;
+
* A customizer can create UI that presents several text input fields serving as such filters, with each applied to a different property.
+
  
 +
{{Hint|When multiple filters are used at the same time, they are combined with "logic and".}}
  
For example. One can customize the ChildArea template to include the following.
+
For performance/usability reasons, the result list is not immediately refreshed as one types in the text box. Instead, it only happens after the ReloadChildListCommand is triggered.
 +
 
 +
However, note that these content-based filters:
 +
* Require a custom [[SYSCLS_CHILDAREATEMPLATE|Child Area template name]] to work. This customizing will not work applied to the UBIKChildArea.
 +
* Work directly on the Children.Items collection. While filters are active, anything derived from this collection (such as Children.Items.Count or custom datasources like [[XAML_Changes_in_UBIK_WinX_3.5#Filtering_by_expressions|ListCollectionView]] / [[Xamarin_XAML#Content_filtering|sfDataSourceExt]]) will also be affected.
 +
<br><br>
 +
 
 +
== Usage ==
 +
For simple text input, it is enough to create a text input control with a TwoWay relationship to the Children.Filter[x].
 +
However, the TwoWay binding doesn't always work well with more advanced implementations, such as selection. In such cases, the alternative is to use the UpdatePropertyFiltersCommand to supply the filter criteria.
 +
Both approaches are described below.
 +
 
 +
=== Text Input ===
 +
<tabs>
 +
<tab name="UWP">
 
<source lang = "xml">
 
<source lang = "xml">
    <Grid>
+
<TextBox
      <Border Background="#8000488E" Visibility="{Binding Children.Filters[SomePropertyName], Converter={StaticResource NullObjOrEmptyStrColConverter}}" />
+
    Text="{Binding Children.Filters[SomePropertyName], Mode=TwoWay, Converter={StaticResource FilterCriterionToValueConverter}}"
      <Border Background="#90707070" Visibility="{Binding Children.Filters[SomePropertyName], Converter={StaticResource NullObjOrEmptyStrVisConverter}}" />
+
    PlaceholderText="SomePropertyName" />
      <TextBox Text="{Binding Children.Filters[SomePropertyName], Mode=TwoWay, Converter={StaticResource FilterCriterionToValueConverter}}"
+
                PlaceholderText="SomePropertyName" BorderThickness="0" Foreground="White" Background="Transparent" />
+
    </Grid>
+
 
</source>
 
</source>
 +
</tab>
  
 +
<tab name="Xamarin">
 +
<source lang = "xml">
 +
<Entry
 +
    Placeholder="Filter by Name"
 +
    Text="{Binding Children.Filters[DESCR], Mode=TwoWay, Converter={StaticResource FilterCriterionToValue}}"/>
 +
</source>
 +
</tab>
 +
</tabs>
  
 
This is shown as a single text box. The two way binding on Text allows the entered text (case insensitive) to be used as the filter value on property "SomePropertyName" (case sensitive).
 
This is shown as a single text box. The two way binding on Text allows the entered text (case insensitive) to be used as the filter value on property "SomePropertyName" (case sensitive).
 +
<br>
  
When multiple filters are used at the same time, they are combined with "logic and".
+
=== Selection ===
 +
Selection is trickier to achieve than direct input, as often a metaproperty's actual value might differ from the text that is displayed for that value. Just think of integer-based statuses, or GUID properties.
  
For performance/usability reasons, the result list is not immediately refreshed as one types in the text box. Instead, it only happens after the [[ReloadChildListCommand]] is triggered.
+
==== List Properties ====
 +
The below examples use a custom ComboBox/Picker control to display a list of items. Because the filter comparison is based on the DisplayValue of the metaproperty, the DisplayText of the selected object is then passed on as a part of the command parameter and later used as a filter criterion to filter for objects that have the same the string.
  
{{Hint|The Borders in the example are not mandatory. They serve as indicators of whether a filter is currently applied on the result list. The PlaceHolderText is optional as well.}}
+
<tabs>
 +
<tab name="UWP">
 +
<source lang = "xml">
 +
xmlns:controls="using:UBIK.WinX.Controls"
 +
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
 +
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
  
=== UpdatePropertyFiltersCommand {{Version/XamarinSince|1.2}} ===
+
<controls:ComboBoxExt
 +
    x:Name="ComboBox"
 +
    PlaceholderText="{Binding Children.Filters[STATUSCOLOR].Value, TargetNullValue='SELECT', FallbackValue='SELECT'}"
 +
    DisplayMemberPath="DisplayText"
 +
    SelectedValuePath="DisplayText"
 +
    SelectedValue="{Binding Children.Filters[STATUSCOLOR].Value}"
 +
    SelectedValueExt="{Binding Children.Filters[STATUSCOLOR].Value}"
 +
    ItemsSource="{Binding Children.Items[0].Properties.AllItems[STATUSCOLOR].MetaProperty.SelectiveList, Converter={StaticResource SelectiveListToItemsConverter}}">
  
The above mentioned two way binding doesn't always work well with all controls and complex bindings. In such cases, the alternative is to use the UpdatePropertyFiltersCommand to supply the filter criteria.
+
    <interactivity:Interaction.Behaviors>
 +
        <core:EventTriggerBehavior EventName="SelectionChanged">
 +
            <core:InvokeCommandAction Command="{Binding Children.UpdatePropertyFiltersCommand}">
 +
                <core:InvokeCommandAction.CommandParameter>
 +
                    <controls:KeyValueList>
 +
                        <controls:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
 +
                        <controls:KeyValueParameter Key="STATUSCOLOR" Value="{Binding SelectedItem.DisplayText, ElementName=ComboBox}" />
 +
                    </controls:KeyValueList>
 +
                </core:InvokeCommandAction.CommandParameter>
 +
            </core:InvokeCommandAction>
 +
        </core:EventTriggerBehavior>
 +
    </interactivity:Interaction.Behaviors>
 +
</controls:ComboBoxExt>
 +
</source>
 +
</tab>
 +
<tab name="Xamarin">
 +
<source lang = "xml">
 +
xmlns:controls="clr-namespace:UBIK.CPL.Controls;assembly=UBIK.CPL"
 +
xmlns:classes="clr-namespace:UBIK.CPL.Classes;assembly=UBIK.CPL">
  
 +
<controls:PickerExt
 +
    x:Name="Filter"
 +
    ItemsSource="{Binding Children.Items[0].Properties.AllItems[STATUSCOLOR].MetaProperty.SelectiveList, Converter={StaticResource SelectiveListToItemsConverter}}"
 +
    ItemDisplayBinding="{Binding DisplayText}"
 +
    SelectionChangedCommand="{Binding Children.UpdatePropertyFiltersCommand}"
 +
    SelectedValuePath="DisplayText"
 +
    SelectedValue="{Binding Children.Filters[STA].Value, Mode=OneWay}">
 +
    <controls:PickerExt.SelectionChangedCommandParameter>
 +
        <classes:KeyValueList>
 +
            <classes:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
 +
            <classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.DisplayText, Source={x:Reference Filter}}" />
 +
        </classes:KeyValueList>
 +
    </controls:PickerExt.SelectionChangedCommandParameter>
 +
</controls:PickerExt>
 +
</source>
 +
</tab>
 +
</tabs>
 +
 +
Note that several elements are required for this customization to work:
 +
* '''SelectedValuePath''' informs the control of which property should be supplied to the command as a filter criteria. This should match what is supplied in your KeyValueParameter.
 +
* '''DisplayMemberPath'''/'''ItemDisplayBinding''' informs the control of which property should be visualized as the displaytext of your selection. Note that this is a binding on Xamarin only.
 +
* In UWP: '''PlaceholderText''' binds to the same value as your SelectedValueExt to display the current selected item. This is a workaround for a failure of the ComboBox control to correctly display an active selection when the control is rendered. In Xamarin, a secondary label is required to display a placeholder text when the Picker's SelectedIndex is null.
 +
 +
Furthermore, this approach makes use of the '''Children.UpdatePropertyFiltersCommand''', which uses the following parameters:
 +
* ClearPropertyFilters: Clear out all existing filters at the current level before executing the command. This is optional and defaults to false;
 +
* All other parameters: KeyValue pairs used as filter criteria where the Keys are the names of the metaproperties by which you want to filter.
 +
 +
==== ItemsSource ====
 +
{{Attention| The '''ItemsSource''' in the above example is a way to populate the selection list dynamically by taking the MetaProperty.SelectiveList items of the STATUSCOLOR property that we are filtering, taken from the first child in the list. This selection list will therefore become empty if all items are filtered out of the Children collection.}}
 +
 +
For simple string properties, it is also possible to hardcode the options in the selection list as follows:
 
<tabs>
 
<tabs>
 +
<tab name="UWP">
 +
  <source lang = "xml">
 +
<x:String>Green</x:String>
 +
<x:String>White</x:String>
 +
<x:String>Yellow</x:String>
 +
  </source>
 +
Simply add the strings as content of the controls:ComboBoxExt.
 +
</tab>
 +
<tab name="Xamarin">
 +
  <source lang = "xml">
 +
<Picker.ItemsSource>
 +
<x:Array Type="{x:Type x:String}">
 +
    <x:String>Green</x:String>
 +
    <x:String>White</x:String>
 +
    <x:String>Yellow</x:String>
 +
</x:Array>
 +
</Picker.ItemsSource>
 +
  </source>
 +
Simply add the Array to the ItemsSource attribute of the Picker or controls:PickerExt.
 +
</tab>
 +
</tabs>
  
<tab name="Xamarin">
+
Note that you will then need to remove references to the DisplayText, as the x:String value becomes the value used to filter.
 +
 
 +
==== GUID Properties ====
 +
The above controls:ComboBoxExt and controls:PickerExt examples can be converted to filter GUID values as follows:
 
<source lang = "xml">
 
<source lang = "xml">
<Grid xmlns:ctrls="clr-namespace:UBIK.CPL.Controls;assembly=UBIK.CPL"
+
Xamarin:
          xmlns:classes="clr-namespace:UBIK.CPL.Classes;assembly=UBIK.CPL">
+
 
    <ctrls:PickerExt
+
<controls:PickerExt
        x:Name="Filter"
+
    x:Name="Plant_Filter"
        ItemsSource="{Binding Properties.AllItems[QUERY].LinkedLevel.Children.Items}"
+
    ItemsSource="{Binding Properties.AllItems[LK_PLANT_QUERY].LinkedLevel.Children.Items}"
        ItemDisplayBinding="{Binding Header}"
+
    ItemDisplayBinding="{Binding Header}"
        SelectionChangedCommand="{Binding Children.UpdatePropertyFiltersCommand}"
+
    SelectionChangedCommand="{Binding Children.UpdatePropertyFiltersCommand}"
        SelectedValuePath="UID"
+
    SelectedValuePath="UID"
        SelectedValue="{Binding Children.Filters[STA].Value, Mode=OneWay}">
+
    SelectedValue="{Binding Children.Filters[LK_PLANT_SECTION].Value, Mode=OneWay}">
        <ctrls:PickerExt.SelectionChangedCommandParameter>
+
    <controls:PickerExt.SelectionChangedCommandParameter>
            <classes:KeyValueList>
+
        <classes:KeyValueList>
                <classes:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
+
            <classes:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
                <classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Filter}}" />
+
            <classes:KeyValueParameter Key="LK_PLANT_SECTION" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Plant_Filter}, Converter={StaticResource FilterValueToCriterion}, ConverterParameter=Content[\&quot;\{0\}\&quot;].Value.ToString().Equals(\&quot;\{1\}\&quot;)\=\=true}" />
            </classes:KeyValueList>
+
        </classes:KeyValueList>
            </ctrls:PickerExt.SelectionChangedCommandParameter>
+
    </controls:PickerExt.SelectionChangedCommandParameter>
    </ctrls:PickerExt>
+
</controls:PickerExt>
</Grid>
+
 
</source>
 
</source>
</tab>
+
<br>
 +
Note that in this example, a Properties.AllItems[LK_PLANT_QUERY] is added to the Content object to provide the list of items displayed by the Picker, as a workaround to the Children.Items[0] approach.
 +
<br><br>
  
<tab name="UWP">
+
== Displaying Results ==
Not yet available.
+
For performance/usability reasons, the result list is not immediately refreshed as one types in the text box. Instead, it only happens after the ReloadChildListCommand is triggered.
</tab>
+
  
</tabs>
+
This can be done on a dedicated button:
 +
<source lang = "xml">
 +
UWP:
  
The example above uses a UBIK.CPL.Controls.PickerExt control to display a list of query result objects (through the "QUERY" property's LinkedLevel). The UID of the selected object is then passed on as a part of the command parameter and later used as a filter criterion to filter for objects that have their "STA" property value containing the UID string.
+
<Button 
* ClearPropertyFilters: Clear out all existing filters at the current level before executing the command. This is optional and defaults to false;
+
    Content="{Binding Filter, Source={StaticResource UBIKIcons}}"  
* All other parameters: Used as filter criteria where the Keys are the names of the properties by which you want to filter.
+
    Style="{StaticResource UBIKSymbolButtonStyle}"
 +
    Command="{Binding ReloadChildListCommand}"/>
 +
</source>
 +
<br>
  
 +
Or in certain cases, can be combined with the filter input to trigger immediately:
 +
<source lang = "xml">
 +
Xamarin:
 +
 +
<Entry.Behaviors>
 +
    <behaviors:EventHandlerBehavior EventName="Completed">
 +
        <behaviors:InvokeCommandAction Command="{Binding ReloadChildListCommand}" />
 +
    </behaviors:EventHandlerBehavior>
 +
</Entry.Behaviors>
 +
</source>
 +
<br>
 +
 +
== Evaluation Criteria ==
 +
By default, the expression used for filtering is Content["PROPERTY_NAME"].DisplayValue.ToLower().Contains(FILTER_VALUE.ToLower())==true.
 +
In other words, it checks whether the specified filter value (as string) is contained in the display value of the property.
  
By default, the expression used for filtering is Content["PROPERTY_NAME"].DisplayValue.ToLower().Contains(FILTER_VALUE.ToLower())==true. In other words, it checks whether the specified filter value (as string) is contained in the display value of the property.
 
 
In more advanced scenarios where a different type of comparison is needed, the example (or more specifically the one KeyValueParameter) can be extended into the following, e.g. comparing whether the specified filter value is equal to the value of the property.
 
In more advanced scenarios where a different type of comparison is needed, the example (or more specifically the one KeyValueParameter) can be extended into the following, e.g. comparing whether the specified filter value is equal to the value of the property.
 
<source lang = "xml">
 
<source lang = "xml">
<classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Filter}, Converter={StaticResource FilterValueToCriterion}, ConverterParameter=Content[\&quot;\{0\}\&quot;].Value.ToString().Equals(\&quot;\{1\}\&quot;)}" />
+
<classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Filter}, Converter={StaticResource FilterValueToCriterion}, ConverterParameter=Content[\&quot;\{0\}\&quot;].Value.ToString().Equals(\&quot;\{1\}\&quot;)\=\=true}" />
 
</source>
 
</source>
{{Hint|"&amp;quot;" and "\" are used for escaping the special characters in XAML and C# code respectively. "{0}" and "{1}" are placeholders and get replaced by the property name and the filter value. The end expression being executed in this example is Content["PROPERTY_NAME"].Value.ToString().Equals(FILTER_VALUE).}}
+
<br>
 +
 
 +
{{Hint|"&amp;quot;" and "\" are used for escaping the special characters in XAML and C# code respectively. "{0}" and "{1}" are placeholders and get replaced by the property name and the filter value. The end expression being executed in this example is <code>Content["PROPERTY_NAME"].Value.ToString().Equals(FILTER_VALUE)&#61;&#61;true</code>}}
 +
<br><br>
 +
 
 +
== UI Customizing ==
 +
 
 +
=== Filtered Indicator ===
 +
You can also customize UI elements to indicate that filters are active.
 +
<source lang = "xml">
 +
UWP:
 +
 
 +
<Border
 +
    Background="#8000488E"
 +
    Visibility="{Binding Children.Filters[SomePropertyName], Converter={StaticResource NullObjOrEmptyStrColConverter}}" />
 +
</source>
 +
<br>
 +
The above border is shown when a filter is active.
 +
 
 +
Other bindings exist on the Filters collection. Use [[Developer_Mode|Developer Mode]] to see what possibilities are available. Some examples are:
 +
<source lang = "xml">
 +
Children.Filters.Filters.Count
 +
</source>
 +
<br>
 +
<source lang = "xml">
 +
Children.Filters.IsActive
 +
</source>
 +
<br><br>
 +
 
 +
== Troubleshooting ==
 +
As previously mentioned, only areas with a custom Child Area template name can make use of filters.
 +
When Filters (or Sorting) are applied, a config file is created at '''Local State/Configs''' where the filter data is written and persisted.
 +
 
 +
{{Attention|Note that during a trial and error phase, filters may be applied that makes a child list fully/partially filtered out of view. }}
 +
This file can be used to inspect how a xaml implementation is being translated into filter criteria.
  
{{Category/Version|2.6.1}}
+
Deleting the file (with the client closed) will remove forget any filters.
  
 
[[Category:2.6.1|Property Based Content Filters]]
 
[[Category:2.6.1|Property Based Content Filters]]

Latest revision as of 10:42, 27 June 2024

The UI can be customized to accept user inputs as filter criteria, and reduce the entire child list to a sub-list based on property values that contain that text. Each filter is 'attached' to a single metaproperty, and multiple filters can be applied at once.

IC Hint square.pngWhen multiple filters are used at the same time, they are combined with "logic and".

For performance/usability reasons, the result list is not immediately refreshed as one types in the text box. Instead, it only happens after the ReloadChildListCommand is triggered.

However, note that these content-based filters:

  • Require a custom Child Area template name to work. This customizing will not work applied to the UBIKChildArea.
  • Work directly on the Children.Items collection. While filters are active, anything derived from this collection (such as Children.Items.Count or custom datasources like ListCollectionView / sfDataSourceExt) will also be affected.



Usage

For simple text input, it is enough to create a text input control with a TwoWay relationship to the Children.Filter[x]. However, the TwoWay binding doesn't always work well with more advanced implementations, such as selection. In such cases, the alternative is to use the UpdatePropertyFiltersCommand to supply the filter criteria. Both approaches are described below.

Text Input

UWP

<TextBox
   Text="{Binding Children.Filters[SomePropertyName], Mode=TwoWay, Converter={StaticResource FilterCriterionToValueConverter}}"
   PlaceholderText="SomePropertyName" />

Xamarin

<Entry
   Placeholder="Filter by Name"
   Text="{Binding Children.Filters[DESCR], Mode=TwoWay, Converter={StaticResource FilterCriterionToValue}}"/>

This is shown as a single text box. The two way binding on Text allows the entered text (case insensitive) to be used as the filter value on property "SomePropertyName" (case sensitive).

Selection

Selection is trickier to achieve than direct input, as often a metaproperty's actual value might differ from the text that is displayed for that value. Just think of integer-based statuses, or GUID properties.

List Properties

The below examples use a custom ComboBox/Picker control to display a list of items. Because the filter comparison is based on the DisplayValue of the metaproperty, the DisplayText of the selected object is then passed on as a part of the command parameter and later used as a filter criterion to filter for objects that have the same the string.

UWP

xmlns:controls="using:UBIK.WinX.Controls"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"

<controls:ComboBoxExt
   x:Name="ComboBox"
   PlaceholderText="{Binding Children.Filters[STATUSCOLOR].Value, TargetNullValue='SELECT', FallbackValue='SELECT'}"
   DisplayMemberPath="DisplayText"
   SelectedValuePath="DisplayText"
   SelectedValue="{Binding Children.Filters[STATUSCOLOR].Value}"
   SelectedValueExt="{Binding Children.Filters[STATUSCOLOR].Value}"
   ItemsSource="{Binding Children.Items[0].Properties.AllItems[STATUSCOLOR].MetaProperty.SelectiveList, Converter={StaticResource SelectiveListToItemsConverter}}">

    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="SelectionChanged">
            <core:InvokeCommandAction Command="{Binding Children.UpdatePropertyFiltersCommand}">                                               
                <core:InvokeCommandAction.CommandParameter>
                    <controls:KeyValueList>
                        <controls:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
                        <controls:KeyValueParameter Key="STATUSCOLOR" Value="{Binding SelectedItem.DisplayText, ElementName=ComboBox}" />
                    </controls:KeyValueList>
                </core:InvokeCommandAction.CommandParameter>
            </core:InvokeCommandAction>
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</controls:ComboBoxExt>

Xamarin

xmlns:controls="clr-namespace:UBIK.CPL.Controls;assembly=UBIK.CPL"
xmlns:classes="clr-namespace:UBIK.CPL.Classes;assembly=UBIK.CPL">

<controls:PickerExt
   x:Name="Filter"
   ItemsSource="{Binding Children.Items[0].Properties.AllItems[STATUSCOLOR].MetaProperty.SelectiveList, Converter={StaticResource SelectiveListToItemsConverter}}"
   ItemDisplayBinding="{Binding DisplayText}"
   SelectionChangedCommand="{Binding Children.UpdatePropertyFiltersCommand}"
   SelectedValuePath="DisplayText"
   SelectedValue="{Binding Children.Filters[STA].Value, Mode=OneWay}">
    <controls:PickerExt.SelectionChangedCommandParameter>
        <classes:KeyValueList>
            <classes:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
            <classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.DisplayText, Source={x:Reference Filter}}" />
        </classes:KeyValueList>
    </controls:PickerExt.SelectionChangedCommandParameter>
</controls:PickerExt>

Note that several elements are required for this customization to work:

  • SelectedValuePath informs the control of which property should be supplied to the command as a filter criteria. This should match what is supplied in your KeyValueParameter.
  • DisplayMemberPath/ItemDisplayBinding informs the control of which property should be visualized as the displaytext of your selection. Note that this is a binding on Xamarin only.
  • In UWP: PlaceholderText binds to the same value as your SelectedValueExt to display the current selected item. This is a workaround for a failure of the ComboBox control to correctly display an active selection when the control is rendered. In Xamarin, a secondary label is required to display a placeholder text when the Picker's SelectedIndex is null.

Furthermore, this approach makes use of the Children.UpdatePropertyFiltersCommand, which uses the following parameters:

  • ClearPropertyFilters: Clear out all existing filters at the current level before executing the command. This is optional and defaults to false;
  • All other parameters: KeyValue pairs used as filter criteria where the Keys are the names of the metaproperties by which you want to filter.

ItemsSource

IC Attention.png The ItemsSource in the above example is a way to populate the selection list dynamically by taking the MetaProperty.SelectiveList items of the STATUSCOLOR property that we are filtering, taken from the first child in the list. This selection list will therefore become empty if all items are filtered out of the Children collection.

For simple string properties, it is also possible to hardcode the options in the selection list as follows:

UWP

<x:String>Green</x:String>
<x:String>White</x:String>
<x:String>Yellow</x:String>

Simply add the strings as content of the controls:ComboBoxExt.

Xamarin

<Picker.ItemsSource>
        <x:Array Type="{x:Type x:String}">
            <x:String>Green</x:String>
            <x:String>White</x:String>
            <x:String>Yellow</x:String>
        </x:Array>
</Picker.ItemsSource>

Simply add the Array to the ItemsSource attribute of the Picker or controls:PickerExt.

Note that you will then need to remove references to the DisplayText, as the x:String value becomes the value used to filter.

GUID Properties

The above controls:ComboBoxExt and controls:PickerExt examples can be converted to filter GUID values as follows:

Xamarin:

<controls:PickerExt
   x:Name="Plant_Filter"
   ItemsSource="{Binding Properties.AllItems[LK_PLANT_QUERY].LinkedLevel.Children.Items}"
   ItemDisplayBinding="{Binding Header}"
   SelectionChangedCommand="{Binding Children.UpdatePropertyFiltersCommand}"
   SelectedValuePath="UID"
   SelectedValue="{Binding Children.Filters[LK_PLANT_SECTION].Value, Mode=OneWay}">
    <controls:PickerExt.SelectionChangedCommandParameter>
        <classes:KeyValueList>
            <classes:KeyValueParameter Key="ClearPropertyFilters" Value="false" />
            <classes:KeyValueParameter Key="LK_PLANT_SECTION" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Plant_Filter}, Converter={StaticResource FilterValueToCriterion}, ConverterParameter=Content[\&quot;\{0\}\&quot;].Value.ToString().Equals(\&quot;\{1\}\&quot;)\=\=true}" />
        </classes:KeyValueList>
    </controls:PickerExt.SelectionChangedCommandParameter>
</controls:PickerExt>


Note that in this example, a Properties.AllItems[LK_PLANT_QUERY] is added to the Content object to provide the list of items displayed by the Picker, as a workaround to the Children.Items[0] approach.

Displaying Results

For performance/usability reasons, the result list is not immediately refreshed as one types in the text box. Instead, it only happens after the ReloadChildListCommand is triggered.

This can be done on a dedicated button:

UWP:

<Button  
   Content="{Binding Filter, Source={StaticResource UBIKIcons}}"
   Style="{StaticResource UBIKSymbolButtonStyle}"
   Command="{Binding ReloadChildListCommand}"/>


Or in certain cases, can be combined with the filter input to trigger immediately:

Xamarin:

<Entry.Behaviors>
    <behaviors:EventHandlerBehavior EventName="Completed">
        <behaviors:InvokeCommandAction Command="{Binding ReloadChildListCommand}" />
    </behaviors:EventHandlerBehavior>
</Entry.Behaviors>


Evaluation Criteria

By default, the expression used for filtering is Content["PROPERTY_NAME"].DisplayValue.ToLower().Contains(FILTER_VALUE.ToLower())==true. In other words, it checks whether the specified filter value (as string) is contained in the display value of the property.

In more advanced scenarios where a different type of comparison is needed, the example (or more specifically the one KeyValueParameter) can be extended into the following, e.g. comparing whether the specified filter value is equal to the value of the property.

<classes:KeyValueParameter Key="STA" Value="{Binding Path=SelectedItem.UID, Source={x:Reference Filter}, Converter={StaticResource FilterValueToCriterion}, ConverterParameter=Content[\&quot;\{0\}\&quot;].Value.ToString().Equals(\&quot;\{1\}\&quot;)\=\=true}" />


IC Hint square.png"&quot;" and "\" are used for escaping the special characters in XAML and C# code respectively. "{0}" and "{1}" are placeholders and get replaced by the property name and the filter value. The end expression being executed in this example is Content["PROPERTY_NAME"].Value.ToString().Equals(FILTER_VALUE)==true



UI Customizing

Filtered Indicator

You can also customize UI elements to indicate that filters are active.

UWP:

<Border
   Background="#8000488E"
   Visibility="{Binding Children.Filters[SomePropertyName], Converter={StaticResource NullObjOrEmptyStrColConverter}}" />


The above border is shown when a filter is active.

Other bindings exist on the Filters collection. Use Developer Mode to see what possibilities are available. Some examples are:

Children.Filters.Filters.Count


Children.Filters.IsActive



Troubleshooting

As previously mentioned, only areas with a custom Child Area template name can make use of filters. When Filters (or Sorting) are applied, a config file is created at Local State/Configs where the filter data is written and persisted.

IC Attention.pngNote that during a trial and error phase, filters may be applied that makes a child list fully/partially filtered out of view.

This file can be used to inspect how a xaml implementation is being translated into filter criteria.

Deleting the file (with the client closed) will remove forget any filters.