tags:

views:

21

answers:

1

This code generates a Listview with a grid, of multiple name and emails inside TextBox control. I would like to know how can I capture the focus event on one of the TextBox of a row to have the entire ListView row to be selected.

<ListView Name="lstRecipients" ItemsSource="{Binding Path=Recipients}">
    <ListView.Resources>
        <DataTemplate x:Key="tbNameTemplate">
            <TextBox Name="tbName" Text="{Binding Path=Username, ValidatesOnDataErrors=True}"/>
        </DataTemplate>
        <DataTemplate x:Key="tbEmailTemplate">
            <TextBox Name="tbEmail" Text="{Binding Path=Email, ValidatesOnDataErrors=True}"/>
        </DataTemplate>
    </ListView.Resources>
    <ListView.View>
        <GridView x:Name="gvRecipients">
            <GridViewColumn Header="Name" CellTemplate="{StaticResource tbNameTemplate}"/>
            <GridViewColumn Header="Email" CellTemplate="{StaticResource tbEmailTemplate}"/>
        </GridView>
    </ListView.View>
</ListView>
+1  A: 

You can add a handler to the GotFocus event on the TextBox that sets the selected item on the ListView. You can use ItemsControl.ContainerFromElement to get the ListViewItem and ItemContainerGenerator.ItemFromContainer to get the bound data object. In XAML:

<TextBox GotFocus="tbName_GotFocus" Name="tbName" Text="{Binding Path=Username, ValidatesOnDataErrors=True}"/>

In code-behind:

private void tbName_GotFocus(object sender, RoutedEventArgs e)
{
    var container = lstRecipients.ContainerFromElement((DependencyObject)sender);
    if (container != null)
    {
        lstRecipients.SelectedItem = lstRecipients.ItemContainerGenerator
            .ItemFromContainer(container);
    }
}

You could also set the handler on the ListView, since GotFocus is a routed event. You could use this to create a handler that could be shared between ListViews. In XAML:

<ListView GotFocus="lstRecipients_GotFocus" Name="lstRecipients" ItemsSource="{Binding Path=Recipients}">

In code-behind:

private void lstRecipients_GotFocus(object sender, RoutedEventArgs e)
{
    var selector = sender as Selector;
    if (selector != null)
    {
        var container = selector.ContainerFromElement
            ((DependencyObject)e.OriginalSource);
        if (container != null)
        {
            selector.SelectedItem = selector.ItemContainerGenerator
                .ItemFromContainer(container);
        }
    }
}

(If you don't want the TextBox to be editable at all, you could also just set Focusable="False" or use a TextBlock instead of a TextBox and focus would go to the ListView and select the row when the cell was clicked.)

Quartermeister