Thanks for all the help, but it grew increasingly more complex, the farther down I went that path. Also the Predicate filters on the column names as they are in the database, e.g. Invoice.InvoiceID while the RowFilter expects the column names as the column names of the DataTable (the Field Alias of the TypedList).
I now went with an extension of my previous method that creates both Filter at the same time:
// Declarations
private readonly int MAX_RESULTS_INVOICE = Properties.Settings.Default.Max_Results_Invoice;
private readonly int MIN_RESULTS_INVOICE = Properties.Settings.Default.Min_Results_Invoice;
private int invoiceCollectionItemsCount;
private InvoiceAndSupplierRow selectedInvoice;
private enum InvoiceFilterElements
{
Date_From,
Date_To,
Clerk,
[...]
Supplier,
Description,
Total_Count_Filter_Elements
}
private Boolean[] invoiceFilterOn = new Boolean[ (int)InvoiceFilterElements.Total_Count_Filter_Elements ];
private IPredicate[] invoiceFilter = new IPredicate[ (int)InvoiceFilterElements.Total_Count_Filter_Elements ];
private String[] invoiceRowFilter = new String[ (int)InvoiceFilterElements.Total_Count_Filter_Elements ];
private void initInvFilter()
{
for ( int i = 0 ; i < invoiceFilterOn.Length ; i++ )
invoiceFilterOn[ i ] = false;
}
Example Eventhandler:
private void tbxInvFilterDescription_TextChanged(object sender, EventArgs e)
{
invoiceFilterOn[ (int)InvoiceFilterElements.Description ] = ( ( (TextBox)sender ).Text.Length > 0 );
if ( invoiceFilterOn[ (int)InvoiceFilterElements.Description ] )
{
invoiceFilter[ (int)InvoiceFilterElements.Description ] =
new FieldLikePredicate(InvoiceFields.Description, "%" + ( (TextBox)sender ).Text + "%");
invoiceRowFilter[ (int)InvoiceFilterElements.Description ] =
"Description LIKE '%" + ( (TextBox)sender ).Text + "%'";
}
doFilterInvoices();
}
The "stitching together":
private IPredicateExpression getInvoiceFilter()
{
PredicateExpression predExp = new PredicateExpression(InvoiceFields.InvoiceID > 0); // *)
for ( int i = 0 ; i < (int)InvoiceFilterElements.Total_Count_Filter_Elements ; i++ )
{
if ( invoiceFilterOn[ i ] ) { predExp.AddWithAnd(invoiceFilter[ i ]); }
}
return predExp;
}
private String getInvoiceRowFilter()
{
String rowFilter = "";
int i = 0;
for ( ; i < (int)InvoiceFilterElements.Total_Count_Filter_Elements ; i++ )
{
if ( invoiceFilterOn[ i ] )
{
rowFilter = invoiceRowFilter[ i ];
break;
}
}
i++;
for ( ; i < (int)InvoiceFilterElements.Total_Count_Filter_Elements ; i++ )
{
if ( invoiceFilterOn[ i ] )
{
rowFilter += " AND " + invoiceRowFilter[ i ];
}
}
return rowFilter;
}
*) the invoices with negative IDs contain management information and are not "normal" - the users never see them.
And the actual filtering:
private void doFilterInvoices()
{
IPredicateExpression filter = getInvoiceFilter();
invoiceAndSupplierTypedList.DefaultView.RowFilter = getInvoiceRowFilter();
if ( ( dgvInvoice.Rows.Count < MIN_RESULTS_INVOICE
&& invoiceAndSupplierTypedList.GetDbCount(false, filter) > dgvInvoice.Rows.Count )
// database may contain more elements
|| ( dgvInvoice.Rows.Count == invoiceCollectionItemsCount
&& invoiceCollectionItemsCount < MAX_RESULTS_INVOICE ) )
// filter weakened, fetch more
{
refetchInvoices(filter);
}
}
private void refetchInvoices(IPredicateExpression filter)
{
//refetch from Database with the selected Filters
Status = "Loading invoices...";
invoiceAndSupplierTypedList.Clear();
invoiceAndSupplierTypedList.Fill(MAX_RESULTS_INVOICE, invoiceSorter, false, filter);
invoiceCollectionItemsCount = invoiceAndSupplierTypedList.Count;
Status = "";
}
I did some testing and it queries remarkably seldom, even though it reacts on each change of input. At the moment the MIN/MAX are at 50 / 200.