How to get the SelectedItem in a ListView when a contained component is touched?

Will.ItraxWill.Itrax CAMember ✭✭✭

I have a ListView with some Labels, a Toggle and an Entry. There are several records in the ListView. When I touch a Toggle, the OnToggle brings me to the OnToggle method. What I need is to know is what Item that Toggle is part of. The same goes for the Entry.

If I just tap on the Toggle (without tapping on the cell), then in the OnToggle I get a null for MyListView.SelectedItem.

If I tap on the cell and then tap the Toggle, then in the OnToggle I do get a value for MyListView.SelectedItem. However, if I then tap on another Toggle (without tapping on the new cell) the SelectedItem does not change and that is not good.

Any insight is greatly appreciated. Now, here is the XAML:

       <ListView x:Name="MyListView"  SeparatorVisibility="None"  BackgroundColor="Black" HasUnevenRows="True" >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <StackLayout Orientation="Vertical" Margin="0,0,0,10" BackgroundColor="White">

                                <StackLayout Orientation="Horizontal">
                                    <Label Text="{Binding trq.tech_reportID}" FontSize="18"  BackgroundColor="White" TextColor="Black"
                                           MinimumWidthRequest="40"/>
                                    <Label Text="{Binding trq.questions}" FontSize="18"  BackgroundColor="White" TextColor="Black"/>
                                </StackLayout>

                                <StackLayout Orientation="Horizontal">
                                    <Label Text="No" TextColor="Black" IsVisible="{Binding ShowToggle}" FontSize="18" />                                        
                                    <Switch x:Name="AnswerToggle"  
                                        IsEnabled="True" IsToggled="{Binding AnswerToggle}"
                                        IsVisible="{Binding ShowToggle}"
                                        BackgroundColor="Black"  Toggled="Answer_Toggled"/>
                                    <Label Text="Yes" TextColor="Black" IsVisible="{Binding ShowToggle}" FontSize="18" />
                                </StackLayout>

                                <StackLayout Orientation="Vertical" Margin="0,0,0,0"  BackgroundColor="Black" >
                                    <Entry x:Name="Explanation"   Text="{Binding tr.explanation , Mode=TwoWay}" 
                                           FontSize="18"  BackgroundColor="White" 
                                           TextColor="Black" Placeholder="Explanation" Margin="0,3,0,0" 
                                           MinimumWidthRequest="200"  TextChanged="Entry_TextChanged" />
                                </StackLayout>

                            </StackLayout>
                        </ViewCell.View>

                    </ViewCell>

                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Answers

  • N_BauaN_Baua INMember ✭✭✭✭✭
    edited August 4

    @Will.Itrax,

    Well, I don't know why you require both Toggle (switch control) and Tap (on viewcell), You sure will have your reasons.

    BTW, Have you tried using the 'Behaviors' and turning Events to commands. Read the blog-post to see what I mean

    Also I can see you're mixing two concepts here MVVM command as well as code behind Events (for example TextChanged="Entry_TextChanged" in your XAML above, please don't do that.

    Hope this helps.

    Regards,
    N Baua

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @N_Baua Thanks for your comments. As a result, I have looked into 'Behaviors'. I almost have it working but the weekend arrived.

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @N_Baua I was able to attach a command to a Switch's Toggled event using Behaviors but only when the Switch was in a StackPanel on the page. When the Switch was placed in a ListView I was not able to use Behaviors to do anything on the Toggled event. I was not able to come up with the right syntax.
    I did find a pragmatic solution. In the class supplying data for the ListView, when the bool which supplied the data for the Toggle got changed, I determined that I had access to the rest of the record. That worked in this case.
    When I come across a better solution, then I can apply it here.

  • N_BauaN_Baua INMember ✭✭✭✭✭

    @Will.Itrax

    Glad to hear that, you got it almost working for you.

  • PandukaWeerasekaraPandukaWeerasekara USMember ✭✭

    Hi @Will.Itrax
    Can you kidly tell me the solution which finally worked ? because i am unable to get the toggle switch behavior in the code behind.
    thanks

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @PandukaWeerasekara Here are some snippets of code that are the key parts to make the Switch work for me.
    Note: Some parts are edited without recompiling so they may need some cleaning up.

    The easy part, some XAML for the Listview:

    <ListView x:Name="Employee_LV"    BackgroundColor="Transparent"                 
     ItemTapped="LV_ItemTapped"
      HasUnevenRows="True" >
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
    
            <Frame HasShadow="True" OutlineColor="Black" Padding="10" Margin="5,5,5,5"  >
    
          <Grid Padding="5" >
        <Grid.RowDefinitions>
          <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions>
    
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="1*"></ColumnDefinition>
          <ColumnDefinition Width="5*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
    
        <Switch Grid.Row="0" Grid.Column="0"  IsToggled="{Binding Selected}" BackgroundColor="White"/>
        <Label Grid.Row="0" Grid.Column="1" Text="{Binding Name}" FontSize="20" TextColor="Black" />
    
          </Grid>
            </Frame>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    

    This results in displaying a switch and a person's name.

    The listview gets data from an ObservableCollection of Employee. In OnAppearing I have:

    Employee_LV.ItemsSource = OCEmployee;

    One of the fields in Employee is a bool "Selected" which is bound to the Switch. So, when the switch is tapped, it toggles and the Selected field also toggles.

    My issue was that I wanted to toggle the switch when the row in the grid was tapped. For that I used:

        void LV_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            Employee emp = e.Item as Employee;
            emp.Selected = !emp.Selected;
            ((ListView)sender).SelectedItem = null; // de-select the row
        }
    

    As always, if there is a better way to do this I am happy to learn of it.

Sign In or Register to comment.