Skip to main content
Version: Next

Filtres insensibles aux accents dans les vues

Voici un code à ajouter dans les vues pour rendre le filtre insensible aux accents sur certaines colonnes : Par exemple si l'utilisateur tape "qualite" , on trouvera "qualite" mais aussi "qualité" .

Attention :

  1. l'utilisation de ce code retire dans la vue la partie filtre : image.png

en bas de la vue. 2. Dans les colonnes impactées, le choix de l'opérateur (contient, commence par , égal ...) n'est plus disponible mais est "Contient" 3. Les colonnes dont on veut modifier le filtre sont listées dans "columnToFilter" ( il s'agit de la colonne donc si on affiche un titre en tant que Champ texte mais que la colonne est "id" , il faut indiquer id.)

// CODE A PLACER DANS LA PARTIE HAUTE DE L'ONGLET CODE DE LA VUE
RegisterCriteria();
// CODE A PLACER DANS LA PARTIE BASSE DE L'ONGLET CODE DE LA VUE
// indiquer ici le nom des colonnes à prendre en compte (nom de la colonne sql)
string[] columnToFilter = new string[] { "id", "Etape", "Intervenant" };

// Initialisation du custom contains
void RegisterCriteria()
{
// masquer la barre de filtre du bas (bug devexpress)
Grid.Settings.ShowFilterBar = GridViewStatusBarMode.Hidden;

// enregistrer l'opérateur customisé
if( DevExpress.Data.Filtering.CriteriaOperator.GetCustomFunction( "ContainsAccentIncensitive" ) == null )
DevExpress.Data.Filtering.CriteriaOperator.RegisterCustomFunction(new ContainsAccentIncensitiveOperator());

// Abonnements aux événements de gestion des filtres
Grid.ProcessColumnAutoFilter += Grid_ProcessColumnAutoFilter;
Grid.AutoFilterCellEditorInitialize += Grid_AutoFilterCellEditorInitialize;

foreach( GridViewColumn tmp in Grid.Columns )
{

GridViewEditDataColumn col = tmp as GridViewEditDataColumn;

if( col != null && columnToFilter.Contains( col.FieldName ) )
{
col.Settings.AutoFilterCondition = AutoFilterCondition.Contains;
col.Settings.ShowFilterRowMenu = DevExpress.Utils.DefaultBoolean.False;
}
}
}

// Méthode utilitaire pour filtrer les chaines des caractères accentués
static string RemoveDiacritics(string text)
{
string formD = text.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();

foreach (char ch in formD)
{
System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(ch);
if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
{
sb.Append(ch);
}
}

return sb.ToString().Normalize(NormalizationForm.FormC);
}

// The custom implementation of the operator
public class ContainsAccentIncensitiveOperator : DevExpress.Data.Filtering.ICustomFunctionOperator
{

public object Evaluate(params object[] operands)
{
return ( RemoveDiacritics( (string)operands[0] ).ToUpperInvariant() ).Contains( RemoveDiacritics( (string)operands[1] ).ToUpperInvariant() );
}

public string Name
{
get { return "ContainsAccentIncensitive"; }
}

public Type ResultType(params Type[] operands)
{
return typeof(bool);
}
}

// Création du critère de filtrage
void Grid_ProcessColumnAutoFilter(object sender, ASPxGridViewAutoFilterEventArgs e)
{
if ( columnToFilter.Contains( e.Column.FieldName ) )
{
// s'il y as déja un filtre sur cette colonne
// ==> il faut le retirer de l'expression de filtrage globale avant d'injecter la nouvelle valeur du filtre
DevExpress.Data.Filtering.CriteriaOperator co = DevExpress.Data.Filtering.CriteriaOperator.Parse(Grid.FilterExpression);
if (co is DevExpress.Data.Filtering.GroupOperator)
{
DevExpress.Data.Filtering.GroupOperator go = co as DevExpress.Data.Filtering.GroupOperator;
DevExpress.Data.Filtering.CriteriaOperator operand = go.Operands.Find(op => op.LegacyToString().Contains("ContainsAccentIncensitive") && op.LegacyToString().Contains(e.Column.FieldName) );
if (operand is DevExpress.Data.Filtering.CriteriaOperator)
go.Operands.Remove(operand);
Grid.FilterExpression = go.LegacyToString();
}
else if (co is DevExpress.Data.Filtering.CriteriaOperator)
{
string filter = co.LegacyToString();
if (filter.Contains("ContainsAccentIncensitive") && filter.Contains( e.Column.FieldName) )
Grid.FilterExpression = string.Empty;
}

// injection de la nouvelle règle de filtrage
e.Criteria = DevExpress.Data.Filtering.CriteriaOperator.Parse(
"Custom( 'ContainsAccentIncensitive', [" + e.Column.FieldName +"], '" + e.Value + "')"
);

}
}


void Grid_AutoFilterCellEditorInitialize(object sender, ASPxGridViewEditorEventArgs e)
{
// pour l'affichage de la valeur saisie dans la zone de filtre,
// il faut faire un reverse-engineering de l'expression complète
if (columnToFilter.Contains(e.Column.FieldName))
if (!string.IsNullOrEmpty(Grid.FilterExpression) && Grid.FilterExpression.Contains("ContainsAccentIncensitive") )
{
DevExpress.Data.Filtering.CriteriaOperator co = DevExpress.Data.Filtering.CriteriaOperator.Parse(Grid.FilterExpression);
DevExpress.Data.Filtering.CriteriaOperator operand = null;

if (co is DevExpress.Data.Filtering.GroupOperator)
{
DevExpress.Data.Filtering.GroupOperator go = co as DevExpress.Data.Filtering.GroupOperator;
DevExpress.Data.Filtering.CriteriaOperator fo = go.Operands.FirstOrDefault(op => op.LegacyToString().Contains("ContainsAccentIncensitive") && op.LegacyToString().Contains(e.Column.FieldName));
if (fo is DevExpress.Data.Filtering.FunctionOperator )
operand = ((DevExpress.Data.Filtering.FunctionOperator) fo).Operands[2];
}
else
{
if( co.LegacyToString().Contains( e.Column.FieldName ) )
operand = (co as DevExpress.Data.Filtering.FunctionOperator).Operands[2];
}

if (!ReferenceEquals(operand, null))
e.Editor.Value = (operand as DevExpress.Data.Filtering.OperandValue).Value.ToString();
}
}

Code testé sur 2014 SP2 et 2014 SP3

image.png