John Ernest John Ernest - 9 months ago 40
C# Question

UWP setting a ComboBox's SelectedItem when the ItemSource is LINQ

I'm having some trouble getting the SelectedItem to set for a ComboBox when the underlying ItemSource is from a LINQ query.

Here's the code where it sets, the method is coming in from a Cortana voice command. The name of the book when spoken may be different from the written book name because of numbers in the name that I have to spell out, like "first" for example instead of "1".

public void SetBookChapter(string book, int? chapter)
{
Model.BookVoiceName voice = dataLoader.BookVoiceNames.FirstOrDefault(b => b.VoiceBookName.ToLower() == book.ToLower());
if (voice.TotalChapters >= chapter)
{
UpdateChapterText = false;
cmb_Book.SelectedItem = new BookNames { BookName = voice.ActualBookName };
UpdateChapterText = true;
cmb_Chapter.SelectedIndex = chapter.Value - 1;
}
}


When debugging the line for cmb_Book.SelectedItem = ... doesn't set nor does it return any error or information on why, the underlying ItemSource for cmb_Book is set by these properties:

public IEnumerable<BookNames> CurrentBooks
{
get
{
return from b in dataLoader.Translations[TranslationIndex].Books select new BookNames { BookName = b.BookName };
}
}

public IEnumerable<BookNames> BooksInFirstTranslation
{
get
{
return from b in dataLoader.Translations[0].Books select new BookNames { BookName = b.BookName };
}
}


Is there a workaround where I can set the SelectedItem directly whenever a LINQ query is used? I thought maybe by using a known type for IEnumerable would help, but it doesn't.

Answer Source

Equality doesn't work because you're creating different instances of BookNames in the items source and in the selected item.

One workaround could be to override the equality comparer of BookNames:

public class BookNames
{
    public string BookName { get; set; }

    public override bool Equals(object obj)
    {
        var bookNames = obj as BookNames;

        return bookNames != null && this.BookName.Equals(bookNames.BookName);
    }

    public override int GetHashCode()
    {
        return this.BookName?.GetHashCode() ?? 0;
    }
}

This way, even if SelectedItem has a different instance, the ComboBox will be able to match it to another item as long as the name is identical.