1

I am developing an Universal Windows app. It contains a ListView to display a set of terms and their definitions. The ListView is bound to a DataSource.cs file in the XAML part. The ListView is showing correctly.

There is a requirement to add a search-box to filter out the ListView items as the keyword is typed in. I have confirmed that the search-box is able to filter out the terms from the DataSource.cs by using Debug.Writeline("").

The issue I am facing is that I'm unable to hide the items which have not been selected by the search-box. The actual searching is happening inside of a foreach loop that contains an if block. Hence, my idea was to hide the ListView.slectedItem in the corresponding else block. The trouble is that this approach throws an exception that says,

A first chance exception of type 'System.Exception' occurred in mscorlib.dll An exception of type 'System.Exception' occurred in mscorlib.dll but was not handled in user code Additional information: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

The program 'XXXX.exe' has exited with code -1 (0xffffffff).

Here I have provided the code.

XAML

<ListView x:Name="ItemListView" 
    Margin="0,0,0,4" 
    Height="Auto" 
    ItemTemplate="{StaticResource MessageListImageTemplate}" 
    ShowsScrollingPlaceholders="False"
    ContainerContentChanging="ItemListView_ContainerContentChanging"
    ItemClick="ItemListView_ItemClick"        
    IsItemClickEnabled="True" 
    SelectionMode="None">

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Padding" Value="0,0,0,20"/>
            </Style>
        </ListView.ItemContainerStyle>

</ListView>

<SearchBox  
    x:Name="search" 
    PlaceholderText="Search for a term"  
    SuggestionsRequested="search_SuggestionsRequested" 
    SearchHistoryEnabled="False" `
    Grid.Row="1"
    HorizontalAlignment="Left" 
    VerticalAlignment="Center" 
    Margin="50,0,0,0" 
    Height="50" />

C#

StoreData storeData = null;

public MainPage()
{
    storeData = new StoreData();

    //setting the ListView source to the sample data 
    ItemListView.ItemsSource = storeData.Collection;

    // making sure the first item is the selected item
    ItemListView.SelectedIndex = 0;           
}

void ItemListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    ItemViewer iv = args.ItemContainer.ContentTemplateRoot as ItemViewer;

    if (args.InRecycleQueue == true)
    {
        iv.ClearData();
    }
    else if (args.Phase == 0)
    {
        iv.ShowTitle(args.Item as Item);

        // Register for async callback to visualize Title asynchronously
        args.RegisterUpdateCallback(ContainerContentChangingDelegate);
    }
    else if (args.Phase == 1)
    {
        iv.ShowDescription();
        args.RegisterUpdateCallback(ContainerContentChangingDelegate);
    }

    // For imporved performance, set Handled to true since app is visualizing the data item
    args.Handled = true;
}

private TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> ContainerContentChangingDelegate
{
    get
    {
        if (_delegate == null)
        {
            _delegate = new TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs>                (ItemListView_ContainerContentChanging);
        }
            return _delegate;
    }
}

private TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> _delegate;

private void search_SuggestionsRequested(Object sender, SearchBoxSuggestionsRequestedEventArgs e)
{

    IEnumerable<Item> suggestionList = (IEnumerable<Item>)storeData.Collection.Cast<Item>();

    string queryText = e.QueryText;

    if (!string.IsNullOrEmpty(queryText))
    {

        Windows.ApplicationModel.Search.SearchSuggestionCollection suggestionCollection = e.Request.SearchSuggestionCollection;

        foreach (Item suggestedItem in suggestionList)
        {
            String suggestion = suggestedItem.Title;
            Debug.WriteLine(suggestion);

            if (suggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
            {
                suggestionCollection.AppendQuerySuggestion(suggestion);

            }

            else
            {
                 //this is the line throwing the exception     
                 ItemListView.Items.RemoveAt(ItemListView.SelectedIndex); 
            }
        }
    }
}

I am new to Windows development. Any and all help will be appreciated.

siddu
  • 23
  • 5

1 Answers1

1

This has got to be quick because I'm just about to leave. In short, you need two collections to filter data, one original, untouched collection and one filtered collection to display. Let's say you have data bound a string property named FilterText to the UI (the one that users type into to filter the collection).

You can use this string to filter the collection using LinQ like this:

if (FilterText == string.Empty) 
    FilteredCollection = new ObservableCollection<strging>(OriginalCollection);
else FilteredCollection = new ObservableCollection<strging>(
    OriginalCollection.Where(s => s.StartsWith(FilterText)));

Put this code into a method and call it from the FilterText setter so that it updates the collection after each character is typed. Of course, you'll need to set the Binding.UpdateSourceTrigger property on the FilterText Binding to PropertyChanged to make this work as expected.

Sheridan
  • 68,826
  • 24
  • 143
  • 183