Last modified on 2 June 2023, at 09:35

Draft Roadmap

Revision as of 09:35, 2 June 2023 by REP (Talk | contribs)

This page describes how to customize filtered lists that additionally accept user inputs as filter criteria. The following examples are based on the Children.Items collection, however, Properties or Documents can be filtered too. (True?)

IC Attention.pngThis implementation is different from Property-Based Filtering, that simply applies the inputs to the unfiltered child list. Property Based Content Filters

Four elements are required for Custom Filtering:

  • Input field - for user inputs.
  • EvalExpression - for converting user inputs into a filter expression.
  • Collection Filter - for applying the expression to a collection.
  • Items control - for displaying the filtered items.



This system acts dynamically to output the filtered list, without requiring the use of an Evaluation button, and directly outputs all items that match the filter input.

This page will describe the basic implementation, but also how to extend the functionality:

  • For multiple inputs.
  • For filtering based on user input and object Meta data.


Basic Implementation

To build the filter in XAML, you will need to place an EvalExpression and a Collection Filter in the Resources of your container (most likely, a Grid), and the Input and List output in the container's content.

The following namespaces are be used:

UWP

xmlns:controls="using:UBIK.WinX.Controls"
xmlns:cv="using:UBIK.WinX.UI.CollectionView"

Xamarin

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

Resources

It is recommended to place the EvalExpression and Collection Filter into the <Grid.Resources>, as follows. For the Collection Filter, use ListCollectionView for UWP & Content filtering for Xamarin:

UWP

<Grid.Resources>
       <controls:EvalExpression x:Name="FilterExpression" Context="{Binding}" Expression="(P1==null||P1==&quot;&quot;) ? &quot;true&quot; : P0">
              <controls:EvalExpressionParameter Name="P0"
                    Value="{Binding ElementName=InputTextboxName, Path=Text, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
              <controls:EvalExpressionParameter Name="P1"
                    Value="{Binding ElementName=InputTextboxName, Path=Text}" />
       </controls:EvalExpression>

       <cv:ListCollectionView
             x:Key="FilterView"
             Expression="{Binding ElementName=FilterExpression, Path=Result}"
             ItemsSource="{Binding Children.Items}" />
</Grid.Resources>
IC Attention.pngNote that the EvalExpression uses x:Name, which requires the 'ElementName' syntax seen in the cv:ListCollectionView.

Xamarin

<Grid.Resources>
       <controls:EvalExpression x:Key="FilterExpression" Expression="(P1==null||P1==&quot;&quot;) ? &quot;true&quot; : P0" Context="{Binding}">
              <controls:EvalExpressionParameter Name="P0" Value="{Binding Path=Text, Source={x:Reference InputEntry}, Converter={StaticResource Formatter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
              <controls:EvalExpressionParameter Name="P1" Value="{Binding Path=Text, Source={x:Reference InputEntry}}" />
       </controls:EvalExpression>

       <controls:SfDataSourceExt
             x:Key="FilterView"
             Expression="{Binding Path=Result, Source={StaticResource FilterExpression}}"
             ItemsSource="{Binding Children.Items}" />
</Grid.Resources>

The EvalExpression Expression first checks whether the TextBox input is empty (as this would otherwise incorrectly be considered a filter input, whereby the property should be empty) and if so returns the unfiltered list (expression outcome hardcoded to 'true'), otherise, apply the filter (expression outcome is taken from string constructed in ConverterParameter of P0)

There are two important details of the EvalExpressionParameter to note here:

  • The ElementName=InputTextboxName should match exactly to the name of your Input control.
  • The Item.Values["NAME"] should be adapted to refer to the property that should be filtered by this input.


TextBox

The input field is just a basic Textbox/Entry we will use to input the filter criteria value. The only important detail for this input control is the name, which must be passed back to the EvalExpressionParameter.

It will look like this:

UWP

<TextBox x:Name="InputTextboxName" />

Xamarin

<Entry x:Name="InputEntry"/>

Items control

An items control will likely be used for displaying filtered results, such as controls:SelectionBoundListView for UWP & SfListViewExt for Xamarin:

UWP

<controls:SelectionBoundListView
      x:Name="FilterQueryList"    
      ItemsSource="{StaticResource FilterView}" />

Xamarin

<controls:SfListViewExt
      x:Name="FilterQueryResultList"
      ItemsSource="{Binding DisplayItems, Source={StaticResource FilterView}}" />


Multiple User Inputs

It is likely that the customizing is required to work with multiple user inputs for the same filter. In this case, the EvalExpression must be adapted to combine the inputs (most likely using an AND relation, for a 'filtering-down' effect), as well as to deliver the full list when nothing is inputted. Of course, additional TextBox / input controls will be required for every added property.

UWP

<controls:EvalExpression x:Name="Multiple_FilterExpression" Expression="(P1==&quot;&quot; &amp;&amp; P11==&quot;&quot;) ? &quot;true&quot; : P0 +&quot;&amp;&amp;&quot;+ P00" Context="{Binding}">
        <controls:EvalExpressionParameter Name="P0" Value="{Binding ElementName=NAME_InputTextbox, Path=Text, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P1" Value="{Binding ElementName=NAME_InputTextbox, Path=Text}" />
        <controls:EvalExpressionParameter Name="P00" Value="{Binding ElementName=DESCR_InputTextBox, Path=Text, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;DESCR&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P11" Value="{Binding ElementName=DESCR_InputTextBox, Path=Text}" />
</controls:EvalExpression>

Xamarin

<controls:EvalExpression x:Name="Multiple_FilterExpression" Expression="(P1==&quot;&quot; &amp;&amp; P11==&quot;&quot;) ? &quot;true&quot; : P0 +&quot;&amp;&amp;&quot;+ P00" Context="{Binding}">
        <controls:EvalExpressionParameter Name="P0" Value="{Binding Path=Text, Source={x:Reference NAME_InputEntry}, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P1" Value="{Binding Path=Text, Source={x:Reference NAME_InputEntry}}" />
        <controls:EvalExpressionParameter Name="P00" Value="{Binding Path=Text, Source={x:Reference DESCR_InputEntry}, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;DESCR&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P11" Value="{Binding Path=Text, Source={x:Reference DESCR_InputEntry}" />
</controls:EvalExpression>

The above example shows how to combine inputs for two properties, NAME and DESCR. For each additional property you need to:

  • Add the TextBox to the empty check in the first part of the EvalExpression Expression (P1, P11).
  • Add the filter logic to the concatinated filter expression (P0, P00).
IC Attention.pngDue to the escaped syntax required in the Expression,
+&quot;&amp;&amp;&quot;+
is the correct syntax required to concatinate filter expressions together.

Once the additional input controls have been created and referenced as EvalExpressionParameters, and the EvalExpression has been adapted as shown, the filter should already function as required; the Collection Filter and Items Control do not need to be adapted.

Combining User Input and MetaData

A common use of the Collection Filter is to filter child lists based on certain MetaData, such as MetaUID, to present groups of specific object types. Therefore, it is likely that a customizer may need to add hardcoded filter criteria to the EvalExpression, that in addition combine with user input, if any is provided.

The following describes how to implement such a scenario in XAML, using the CategoryBasic Implementation as a starting point.

UWP

<controls:EvalExpression x:Name="MetaUID_FilterExpression" Expression="PX +&quot;&amp;&amp;&quot;+ P0 +&quot;&amp;&amp;&quot;+ P1" Context="{Binding}">
        <controls:EvalExpressionParameter Name="PX" Value="Item.Content.MetaUID.ToString().ToLower()==&quot;6f73cde9-ed38-4cbd-8ca1-4597cc2ae621&quot;" />
        <controls:EvalExpressionParameter Name="P0" Value="{Binding ElementName=NAME_InputTextBox, Path=Text, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P1" Value="{Binding ElementName=DESCR_InputTextBox, Path=Text, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;DESCR&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
</controls:EvalExpression>

Xamarin

<controls:EvalExpression x:Name="MetaUID_FilterExpression" Expression="PX +&quot;&amp;&amp;&quot;+ P0 +&quot;&amp;&amp;&quot;+ P1" Context="{Binding}">
        <controls:EvalExpressionParameter Name="PX" Value="Item.Content.MetaUID.ToString().ToLower()==&quot;6f73cde9-ed38-4cbd-8ca1-4597cc2ae621&quot;" />
        <controls:EvalExpressionParameter Name="P0" Value="{Binding Path=Text, Source={x:Reference NAME_InputEntry}, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;NAME&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
        <controls:EvalExpressionParameter Name="P1" Value="{Binding Path=Text, Source={x:Reference DESCR_InputEntry}, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.Values[&quot;DESCR&quot;].ToLower().Contains(&quot;{0}&quot;.ToLower())==true'}" />
</controls:EvalExpression>
The benefit of this Expression is that there will always be a positive result (as long as objects of the correct MetaUID exist in the collection), therefore it is not necessary to first check if all inputs are null and return 'true', as is the case in the Multiple User Inputs example. In this case, additonal inputs simply need to be added as EvalExpressionParameters and combined in the Expression using
+&quot;&amp;&amp;&quot;+

See also