Changes

HowTo:Implement Custom Filtering

5,425 bytes added, 29 July
/* Filtering a DateTime Property */ Added section on single and open range comparison
{{Hint|For greater control over the input format, it is also possible to provide multiple TextBoxes, which could then either be concatenated in an EvalExpression, or used to filter by the DateTime.Day/Week/Month values of the property individually, if such functionality fits the usecase.}}
[[Category:Client|Custom Filtering]][[Category:Filtering|Custom Filtering]][[Category:Styling|Custom Filtering]][[Category:WinX|Custom Filtering]][[Category:XAML|Implement Custom Filtering]][[Category:Xamarin|Custom Filtering]]<br>
==== Comparison ====
Since the EvalExpression approach utilizes string comparisons, not only is it necessary to format the input string, but the property value must also be formatted to match. The 'yyyy/MM/dd' format includes several measures to create the best conditions for comparing the two strings;
* months and days below the value of 10 cannot be a single digit, but must be padded with a preceding 0 in order to keep the string lengths equivalent; 2032/1/1 cannot be property compared with 2032/12/31 for example, as the strings are different lengths.
* putting the year and month first also improves the chance of a correct comparison, as a day 01 can be after a day 31 if the month and year are greater.
 
{{Attention|For the rest of this section, a DatePicker input is assumed.}}
 
'''Single'''
Single comparison Comparison of a single date against a property value works the same way as other dynamic filters, that is, to compare an item's property value with user in, and filter an item in of a string match is found. For this purpose, Therefore it is sufficient to make use of the previously used .Contains() or .Equals() methods.Remember that the Date attribute is not directly usable from the DatePicker, and it's formatted version received via the Tag attribute or an additional label is what is actually used by the EvalExpressions. <tabs><tab name="UWP"><source lang = "xml"><controls:EvalExpression x:Name="FilterExpression" Context="{Binding}" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP"> <controls:EvalExpressionParameter Name="EXP" Value="{Binding ElementName=DatePicker, Path=Tag, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).Contains(&quot;{0}&quot;)==true'}" /> <controls:EvalExpressionParameter Name="INPUT" Value="{Binding ElementName=DatePicker, Path=Tag}" /></controls:EvalExpression></source> </tab><tab name="Xamarin"><source lang = "xml"><controls:EvalExpression x:Key="FilterExpression" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP " Context="{Binding}"> <controls:EvalExpressionParameter Name="EXP" Value="{Binding Path=Text, Source={x:Reference DateString}, Converter={StaticResource StringFormat}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).Contains(&quot;{0}&quot;)==true'}" /> <controls:EvalExpressionParameter Name="INPUT" Value="{Binding Path=Text, Source={x:Reference DateString}}" /></controls:EvalExpression></source></tab></tabs> 
'''Open Range'''
<br>Open Range denotes a single comparison, however, we are not filtering in items of a specific date, but rather all items with their date property after or before the user input (depending on whether a 'Starting From' or 'Ending By' comparison is implemented.  For range comparison, we use the [https://learn.microsoft.com/en-us/dotnet/api/system.string.compareto?view=net-9.0 Microsoft .CompareTo method]. As documented herethere, this method outputs a -1/0/1 depending on the compared string's location in the range. Our expression can target one output for an 'exclusive' filter (in which the inputted date is not considered for the range), however, a more likely scenario is that the user wants the inputted date included in the filter. This is why the expression in the StringFormatConverter should be defined as either !=-1 or !=1; the instance is either not less than a minimum (where true would be an output of 0 or 1), or not greater than a maximum (true = -1 or 0), respectively. The following example shows a 'Starting From' comparison (0 or 1), where the user property value should be equal to or later than the user's inputted value. <tabs><tab name="UWP - Starting From"><source lang = "xml"><controls:EvalExpression x:Name="FilterExpression" Context="{Binding}" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP"> <controls:EvalExpressionParameter Name="EXP" Value="{Binding Path=Tag, ElementName=DateInput, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).CompareTo(&quot;{0}&quot;)!=&quot;-1&quot;'}" /> <controls:EvalExpressionParameter Name="INPUT" Value="{Binding Path=Tag, ElementName=DateInput}" /></controls:EvalExpression></source></tab> <tab name="UWP - Ending By"><source lang = "xml"><controls:EvalExpression x:Name="FilterExpression" Context="{Binding}" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP"> <controls:EvalExpressionParameter Name="EXP" Value="{Binding Path=Tag, ElementName=DateInput, Converter={StaticResource StringFormatConverter}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).CompareTo(&quot;{0}&quot;)!=&quot;1&quot;'}" /> <controls:EvalExpressionParameter Name="INPUT" Value="{Binding Path=Tag, ElementName=DateInput}" /></controls:EvalExpression></source></tab> <tab name="Xamarin - Starting From"><source lang = "xml"><controls:EvalExpression x:Key="FilterExpression" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP " Context="{Binding}"><controls:EvalExpressionParameter Name="EXP" Value="{Binding Source={x:Reference DateString}, Path=Text, Converter={StaticResource StringFormat}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).CompareTo(&quot;{0}&quot;)!=&quot;-1&quot;'}" /><controls:EvalExpressionParameter Name="INPUT" Value="{Binding Source={x:Reference DateString}, Path=Text}" /></controls:EvalExpression></source></tab> <tab name="Xamarin - Ending By"><source lang = "xml"><controls:EvalExpression x:Key="FilterExpression" Expression="(INPUT==null||INPUT==&quot;&quot;) ? &quot;true==true&quot; : EXP " Context="{Binding}"><controls:EvalExpressionParameter Name="EXP" Value="{Binding Source={x:Reference DateString}, Path=Text, Converter={StaticResource StringFormat}, ConverterParameter='Item.PropertyItems[&quot;DATE&quot;].Value.ToString(&quot;yyyy/MM/dd&quot;).CompareTo(&quot;{0}&quot;)!=&quot;1&quot;'}" /><controls:EvalExpressionParameter Name="INPUT" Value="{Binding Source={x:Reference DateString}, Path=Text}" /></controls:EvalExpression></source></tab> {{Hint|The difference between seeking a 'Staring From' (0, 1) or 'Ending By' comparison (-1, 0) is simply defined in the EXP ConverterParameter expression string, which ends with <noWiki>!=-1</noWiki>, or <noWiki>!=1</noWiki>, respectively.}}</tabs> 
'''Closed Range'''
For range comparison, we use the [https://learn.microsoft.com/en-us/dotnet/api/system.string.compareto?view=net-9.0 Microsoft .CompareTo method]. As documented herethere, this method outputs a -1/0/1 depending on the compared string's location in the range. Our expression can target one output for an 'exclusive' filter (in which the inputted date is not considered for the range), however, a more likely scenario is that the user wants the inputted date included in the filter. This is why the expression in the StringFormatConverter should be defined for start date as !=-1, and for end date as !=1; the instance should be not less than than the start date (where true would be an output of 0 or 1), and not greater than the end date (true = -1 or 0), respectively.
696
edits