5

I have 2 ListViews and a TextBlock. The first ListView1 includes letters in Alphabetical order. And the second ListView2 includes the words that start with the selected letter (in ListView1). When I choose a letter from ListView1 and then click on a word loaded in ListView2, I want to get the definition of this word in a TextBlock.

This is my Xaml:

<ListView
               Width="510"
               x:Name="ListView1"
               ItemsSource="{Binding}" 
               Background="White"
               Foreground="Black"
               TabIndex="1"
               Margin="-7,8,0,0"
               IsSwipeEnabled="False"

               SelectionChanged="ItemListView_SelectionChanged"
               Grid.Row="1"
               HorizontalAlignment="Left">
               <ListView.ItemTemplate>
                   <DataTemplate>
                       <StackPanel>
                           <TextBlock Grid.Row="0"
                           Text="{Binding glossary_letter}"
            Margin="10,0,0,0" 
            TextWrapping="Wrap"
                           Foreground="Black"
            FontSize="24"
            FontWeight="SemiBold"
            VerticalAlignment="Center"/>
                       </StackPanel>
                   </DataTemplate>
               </ListView.ItemTemplate>
           </ListView>
           <ListView  Width="361"
               x:Name="ListView2"
               Background="White"
               Foreground="Black"
               Margin="425,8,230,0"
               Grid.Row="1"
               HorizontalAlignment="Center"
               ItemsSource="{Binding}"
               SelectionChanged="itemListView2_SelectionChanged">
               <ListView.ItemTemplate>
                   <DataTemplate>
                       <StackPanel>
                           <TextBlock Grid.Row="1"
            TextWrapping="Wrap"
                           Foreground="Black"
                           Text="{Binding}"       
            FontSize="24"
            FontWeight="SemiBold"
            VerticalAlignment="Center"/>
                       </StackPanel>
                   </DataTemplate>
               </ListView.ItemTemplate>
           </ListView>
           <StackPanel HorizontalAlignment="Right"
                       Background="White"
                       Width="580"
                       Margin="0,10,0,0" Grid.Row="1" Grid.ColumnSpan="2">
               <TextBlock x:Name="defBlock" Foreground="Black" Text="{Binding glossary_definition}"></TextBlock>
           </StackPanel>

If I click the first time on a letter (ListView1) then on a word (ListView2) it shows me the definition. However the second time I click on a letter, it gives me an OutOfRange Error where the ListView2.SelectedIndex = -1

This is my C# code:

private void ListView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
       {           
           ListView2.ItemsSource = arrayW[ListView1.SelectedIndex];          
       }
   private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
   {
     defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];       
   }

Any idea what is the error I am doing?

yalematta
  • 1,389
  • 1
  • 21
  • 36

2 Answers2

2
private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
   {

    if(ListView2.SelectedIndex >= 0){
         defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];       
    }
    else
    {
         defBlock.Text = arrayDef[ListView1.SelectedIndex][0];//set default selected word.. 
    }
}
Taleb Atoui
  • 114
  • 4
0

The problem
You need to manage your list2 selected index changed handler, as every time you update your list one there is a selected index change on list 2 and as there is no selected index it defaults to -1.

There's a number of ways to do this.
1.

private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
   {
     if(ListView2.SelectedIndex == -1)
     // do something or
     // eg.
     return;
     // or
     throw new IndexOutOfRangeException("Message");
     //or 
     throw new Exception(); // catch all              
   }

2.

I'm not sure how you want your app to look like.

I'd be using two separate pages for this. And have the xaml for your first list view and then a second page is viewed and bound to the selected index of your first page.

So list1, you select and that then is easier to set as the data source in a new page which shows list2, and then you can update your textbox with the details from a selected item. or further, create a third page if you wanted to show more extensive details of the word and it's definition.

This way you will not have problems with your List2 having no selected index as the data source is changed.

3.
Or, Take the binding declarations out of the index changed handler and call them methodically when an index is in List1 is selected.So when the selection of List1 is changed, List 2 is updated in other words, you need to update your data source. edit: and with this it's another way of you controlling the use of error handling to avoid an outofrange exception, as the datasource is updated.

So possibly put the following into a separate method.

private void MyTextMethod(){

    defBlock.Text = arrayDef[ListView1.SelectedIndex][ListView2.SelectedIndex];  
}

private void ListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
   {
     try{

        MyTextMethod)();
     }
     catch(OutOfRangeException){ 
        // do something.
     }
}

out of your selected index changed handler and make a call to a separate method when from within the handler.

4.

Take your binding declaration for list2 from out of your selectedindex change handler for list1.

So you could have a method that will update the binding source of list2 and manage the selected index changed handler. Though this is the least useful suggestion.

Bottom line: You need to have some try and catch, or throw statement managing the outofrange exception, as the second list will have varying lengths and the index on letter As list may be selected at 10, and then the letter X may only have a list of length 1 and there is always the issue of the selectionchange returning a selection of -1.

( You don't actually need to clear list2, it is cleared automatically as the data source is changed (sorry, I didn't make that clear))

  • I created a method: `public void FillWords() { ListView2.Items.Clear(); ListView2.ItemsSource = arrayW[ListView1.SelectedIndex]; }` And I called it from the SelectionChanged event handler of ListView1. But I'm getting a "Catastrophic failure" error on `ListView2.Items.Clear();` – yalematta Nov 06 '15 at 07:52
  • Since I have SelectionMode = SingleMode, I can't use `ListView2.Items.Clear();` I used `ListView2.SelectedItem = null;` but I still get the first error an `OutOfRange` Error where the `ListView2.SelectedIndex = -1` – yalematta Nov 06 '15 at 09:50