paparazzo
paparazzo

Reputation: 45106

Set Focus to TextBox after selection from ListBox

When the user selects a value from the ListBox I want tbEntry to receive focus.
The tbEntry.Focus(); in the SelectedPastEntry set does nothing.
(tbEntry is populated with the value from the ListBox).
The tbEntry.Focus(); in the Button_Click does work.

How to have tbEntry entry receive focus after a selection from ListView?

<TextBox  Grid.Row="1" x:Name="tbEntry" Text="{Binding Path=Entry, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AcceptsReturn="True"/>
<ListBox x:Name="lbPast"  Grid.Row="2" ItemsSource="{Binding Path=PastEntries}" ScrollViewer.VerticalScrollBarVisibility="Visible"
            SelectedItem="{Binding Path=SelectedPastEntry, Mode=TwoWay}"/>
<Button Grid.Row="3" Click="Button_Click" Content="focus"/>


public string SelectedPastEntry 
{
    get { return selectedPastEntry; }
    set 
    {
        selectedPastEntry = null;
        entry = value;
        NotifyPropertyChanged("SelectedPastEntry");
        NotifyPropertyChanged("Entry");
        tbEntry.Focus();
    }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
    tbEntry.Focus();
}

Below works better
For some reason the lbPast.SelectedIndex = -1; makes the focus work some times
The first time an item is selected in lbPast the focus goes to tbEntry
The problem is if the same item is selected again then the lbPast item receives focus
The problem with a select of the same item is that set is not fired
But on the first click I see the get on SelectedPastEntry called and null returned
So don't know why set is not called on the second select of the same item

public string SelectedPastEntry 
{
    get { return selectedPastEntry; }
    set 
    {
        if (selectedPastEntry == value || (string.Compare(selectedPastEntry, entry, true) == 0))
        {
            selectedPastEntry = null;
            lbPast.SelectedIndex = -1;
            NotifyPropertyChanged("SelectedPastEntry");
            tbEntry.Focus();
        }
        //selectedPastEntry = value;
        selectedPastEntry = null;
        lbPast.SelectedIndex = -1;
        NotifyPropertyChanged("SelectedPastEntry");
        entry = value;
        NotifyPropertyChanged("Entry");               
        tbEntry.Focus();
    }
}

This was the fix
I know you are going to doubt this but selectedPastEntry was set to null and saw the get called (by lbPast)
But that did NOT change the value of lbPast.SelectedValue

private void lbPastSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Debug.WriteLine(SelectedPastEntry);   // this is null
    Debug.WriteLine(lbPast.SelectedValue);  // this is not null
    if (lbPast.SelectedIndex != -1)
        lbPast.SelectedIndex = -1;
    if (lbPast.SelectedValue != null)
        lbPast.SelectedValue = null;
    tbEntry.Focus();
}

Upvotes: 1

Views: 1047

Answers (2)

Anatoliy Nikolaev
Anatoliy Nikolaev

Reputation: 22702

Setter of property are not the best place to set the Focus to the Control. Instead of try SelectionChanged event of ListView:

Occurs when the selection of a Selector changes.

Example:

XAML

<ListView SelectionChanged="ListView_SelectionChanged" />

Code-behind

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    tbEntry.Focus();
}

Or you can do this: create a handler for the PropertyChanged event and check what kind of property has been updated:

public MyViewModel() 
{
    MyModel = new MyModel();        
    MyModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MyModel_PropertyChanged);
}

private void MyModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if (e.PropertyName.Equals("SelectedPastEntry")) 
    {
        System.Diagnostics.Debug.WriteLine("SelectedPastEntry changed");
    }            
}

Upvotes: 1

NTinkicht
NTinkicht

Reputation: 1002

Set theActiveControl property of the form and you should be fine

this.ActiveControl = tbEntry;

Upvotes: 0

Related Questions