Results 1 to 3 of 3

Thread: Dynamically building LINQ query to search objects

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Dynamically building LINQ query to search objects

    Hi,

    I am creating a mediaplayer / playlist creator tool that basically imports MP3 songs into playlists (grids). I'm looking to add search functionality where the user can search all open playlists (or a subset of the open playlists). A Playlist is basically a collection of AudioFiles, where an AudioFile is a class that holds the filename of the MP3 file and then exposes the tags (Title, Artist, Album, etc) in public properties.

    The idea is that the user can search for a certain expression (for example "the"), and that he can then choose whether to search in the title, in the title and artist, in the title or artist, in the title, artist and/or album, etc. However, I'm having a hard time implementing this and also having it kind of dynamic.

    At the moment I am simply gathering all the AudioFiles from the open playlists (or from the subset of playlists the user chooses) and then running a simple LINQ query to find those AudioFiles where the Title contains the search text. Then I display the resulting AudioFiles in a new playlist window:
    vb.net Code:
    1. If Not String.IsNullOrWhiteSpace(searchText.Text) Then
    2.             Dim files As New List(Of AudioFile)
    3.  
    4.             ' Gather all the AudioFiles from the relevant windows
    5.             For Each playlistWindow In _MainWindow.PlaylistWindows
    6.                 files.AddRange(playlistWindow.Playlist)
    7.             Next
    8.  
    9.             ' Extract those where the Title contains the search text
    10.             Dim matchingFiles = From f In files
    11.                                 Where f.Title.Contains(searchText.Text)
    12.                                 Select f
    13.  
    14.             Me.OpenPlaylist(matchingFiles)
    15.         End If

    Obviously this works only for querying the title, albums and artists aren't used at all. Also, there are no options like case sensitivity, whole word searching, etc.

    I need to extend this to include these options as well as include searching albums and artists optionally. The user should be able to choose the combination of tags he wants to look in. So for example he could choose Title AND Album (in which case only songs where the search text is in the Title AND in the Album will be returned), he could choose Artist OR Album (returning songs where the searchtext is in the artist OR in the album (or both)), etc.

    I am having a hard time implementing this... Of course I could just write a query for every possible combination, but that will get cumbersome very fast, not to mention that it would be very hard to extend later should I want to add more tags the user can search in.

    So basically I am looking for a way to dynamically run a query like this, keeping into account that the user might want to look for Titles and Albums only, not for Artists, etc.
    Besides that I'm also not really sure how the UI should look either. At the moment I just have three Checkboxes, one for Title, Artist and Album. But how do I let the user distinguish between Titles AND Artists or Titles OR Artists..?

    Thanks for any help!


    EDIT
    In case the AND / OR distinguishing is too hard, I would be happy to start with just letting it default to 'OR', so that the user can check Title and Album for example. If he would then search for 'a' then all songs that contain 'a' in their title as well as all songs that contain 'a' in their album should be returned. I guess that makes it easier, but I still wouldn't know how to dynamically create the LINQ query.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Dynamically building LINQ query to search objects

    You can compose LINQ queries using function syntax, e.g.
    vb.net Code:
    1. If someCondition Then
    2.     query = query.Where(predicate1)
    3. Else
    4.     query = query.Where(predicate2)
    5. End If
    You can append multiple Where calls if desired but note that the predicates will be ANDed together. As far as I'm aware, there's no way to OR multiple predicates. Conditions being ORed must be used within the same Where call.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Dynamically building LINQ query to search objects

    Yeah, the AND is the problem here. By default it needs to be OR, and maybe later I'll try to implement AND as well as an option.

    At the moment I have gotten the OR to work though, using this:
    vb.net Code:
    1. Dim matchingFiles = From f In files _
    2.                                 Where Me.SearchTag(f.Title, searchTitlesCheckbox) _
    3.                                 OrElse Me.SearchTag(f.Artist, searchArtistsCheckbox) _
    4.                                 OrElse Me.SearchTag(f.Album, searchAlbumsCheckbox)
    5.                                 Select f
    and the SearchTag function returns the 'Contains' method if the corresponding checkbox is checked, or it returns False if it's not:
    vb.net Code:
    1. Private Function SearchTag(ByVal tag As String, ByVal checkBox As CheckBox) As Boolean
    2.         If checkBox.IsChecked Then
    3.             Dim sourceText, targetText As String
    4.             If caseSensitiveCheckbox.IsChecked Then
    5.                 sourceText = tag
    6.                 targetText = searchText.Text.Trim()
    7.             Else
    8.                 sourceText = tag.ToLower()
    9.                 targetText = searchText.Text.Trim().ToLower()
    10.             End If
    11.             Return sourceText.Contains(targetText)
    12.         Else
    13.             Return False
    14.         End If
    15.     End Function
    This is easy enough to extend should I want to add more searchable tags (I'd just add more parts to the Where query), but I still don't see any way to let the user choose whether he wants OR or AND...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width