views:

80

answers:

3

I have a list of items that are grouped by their first letter. By clicking a letter the user gets alle entries that begin with that letter.

This does not work for french. If I choose the letter a, items with â are not returned.

What is a good way to return items no matter if they have an accent or not?

                 <%  char alphaStart = Char.Parse("A"); 
                        char alphaEnd = Char.Parse("Z"); %>
                    <%  for (char i = alphaStart; i <= alphaEnd; i++) { %>
                        <% char c = i; %>
                        <% var abcList = Model.FaqList.Where(x => x.CmsHeader.StartsWith(c.ToString())).ToList(); %>
                        <% if (abcList.Count > 0 ) { %> 
                            <div class="naviPkt">
                                <a id="<%= i.ToString().ToUpper() %>" class="naviPktLetter" href="#<%= i.ToString().ToLower() %>"><%= i.ToString().ToUpper() %></a>
                            </div>
                            <ul id="menuGroup<%= i.ToString().ToUpper() %>" class="contextMenu" style="display:none;">
                                <% foreach (var info in abcList) { %>
                                    <li class="<%= info.CmsHeader%>">
                                        <a id="infoId<%= info.CmsInfoId%>" href="#<%= info.CmsInfoId%>" class="abcEntry"><%= info.CmsHeader%></a>
                                    </li>
                                <% } %>                                        
                            </ul>
                        <% } %>

                    <% } %>
+1  A: 

Try using i.ToString().ToUpper(StringComparison.InvariantCultureIgnoreCase). It uses a culture neutral model for case conversion, which should eliminate accents.

LBushkin
This did not work. Words with â were not selected.
Malcolm Frexner
A: 

In addition to LBushkin's answer (which I think will work), you can clean up your alphabet generation.

var A = Char.Parse("A");
var alphabet = Enumerable.Range(0, 26).Select(i => A + i);

Then you can use a foreach loop and forget the whole c = i thing. Also you don't need the .ToUpper() calls because you already have capital lettters.

Ryan
+3  A: 

You can easily remove the diacritic signs (accents, umlaut, cedilla and so on) from the string to test only on the base character. This is done by normalizing the string to Unicode form D and removing the character of category "NonSpacingMark". The following extension method strips a string of its diacritic signs :

    public static string RemoveDiacritics(this string s)
    {
        if (s == null)
            throw new ArgumentNullException("s");
        string formD = s.Normalize(NormalizationForm.FormD);
        string noDiacriticsFormD = new string(
            formD.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                 .ToArray());
        string noDiacritics = noDiacriticsFormD.Normalize(NormalizationForm.FormC);
        return noDiacritics;
    }

Using this method, your code becomes :

var abcList = Model.FaqList.Where(x => x.CmsHeader.RemoveDiacritics().StartsWith(c.ToString())).ToList();
Thomas Levesque