5

I'm trying to create a search box with the controls TextBox and ListBox. When I'm on the TextBox starting to type an event handler GotFocus open the ListBox. I want the ListBox to be closed when the TextBox not on focus. I tried to use the LostFocus event in the TextBox, but it didn't work.

In which event handler should I use? I didn't find a good example implements this mechanism.

Edit: I have something like that:

<Canvas Name="m_MainCanvas" Grid.ColumnSpan="2" >
<Rectangle MouseDown="Canvas_MouseDown" Fill="White" Height="280" HorizontalAlignment="Left" Margin="256,12,0,0" x:Name="m_MainRectangle" RadiusX="0" RadiusY="0" Stroke="Black" StrokeThickness="3" VerticalAlignment="Top" Width="238" />
<TextBox Height="23" Margin="10,0,0,210" Name="m_SearchTextBox" VerticalAlignment="Bottom" BorderThickness="0.5" BorderBrush="#69000000" TextChanged="m_SearchTextBox_TextChanged" FontFamily="Kristen ITC" Text="" FontSize="14" FontWeight="Black" HorizontalAlignment="Left" Width="165" Canvas.Top="86" Canvas.Left="274" LostFocus="m_SearchTextBox_LostFocus"/>
<ListBox  ItemTemplate="{DynamicResource ListBoxItemDataTemplate}" ItemsSource="{Binding}" Name="m_FriendsSearchList" Visibility="Hidden" Background="#FFBCEB85"  Width="181" Height="193"  Canvas.Left="283" Canvas.Top="118">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <EventSetter Event="MouseDoubleClick" Handler="HandleDoubleClickItemToSelect" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

The MouseDown event in the Rectangle control is used to get the TextBox out of focus, but it isn't working.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
galbru
  • 422
  • 1
  • 5
  • 15

1 Answers1

5

something like:

<StackPanel>
  <TextBox>
    <TextBox.Triggers>
      <EventTrigger RoutedEvent="GotFocus">
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Duration="0:0:0"
                              Storyboard.TargetName="lb"
                              Storyboard.TargetProperty="(ListBox.Opacity)"
                              To="1" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
      <EventTrigger RoutedEvent="LostFocus">
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Duration="0:0:0"
                              Storyboard.TargetName="lb"
                              Storyboard.TargetProperty="(ListBox.Opacity)"
                              To="0" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </TextBox.Triggers>
  </TextBox>
  <ListBox x:Name="lb"
            Opacity="0">
    <ListBoxItem Content="A" />
    <ListBoxItem Content="B" />
  </ListBox>
</StackPanel>

However in the above approach the ListBox is still holding the space it resides in. if we instead toggle Visibility to Collapsed, every-time the ListBox becomes Visible other control's are going to start moving to accomodate that.

To avoid both these cases, such things are normally implemented via a Popup

<StackPanel>
  <TextBox x:Name="tb" />
  <Popup Width="{Binding RelativeSource={RelativeSource Self},
                          Path=PlacementTarget.ActualWidth}"
          Placement="Bottom"
          PlacementTarget="{Binding ElementName=tb}">
    <Popup.Style>
      <Style TargetType="{x:Type Popup}">
        <Setter Property="IsOpen"
                Value="False" />
        <Style.Triggers>
          <DataTrigger Binding="{Binding ElementName=tb,
                                          Path=IsFocused}"
                        Value="True">
            <Setter Property="IsOpen"
                    Value="True" />
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </Popup.Style>
    <ListBox>
      <ListBoxItem Content="A" />
      <ListBoxItem Content="B" />
    </ListBox>
  </Popup>
</StackPanel>

^^ You'll still see the same output however you no longer have any control's that have to change position due to the popup changing open / close states.

Update:

Download Link

Remember the Trigger is set based on the TextBox having / losing focus. IF you click somewhere that does not take focus, then you will not see the Popup(ListBox) disappear.

Viv
  • 17,170
  • 4
  • 51
  • 71
  • @Mr.Bean and what does not work for you? Your comment couldn't be any more cryptic. There are "two" approaches mentioned in the answer. If I create a new WPF project in Visual Studio and copy either of the two xaml segments into MainWindow.xaml and run the project they work fine for me. – Viv Jun 13 '13 at 17:59
  • Your example work, but isn't good for me. The TextBox lost focus only when I click on The ListBoxItem and I'm looking for example of TextBox lost focus when I click in any place outside the TextBox, 'ithout affecting the events of other controls (like Button, i.e if the TextBox is on focus, the ListBox is open, when I click on a button, the TextBox will lost his focus and the click event for the Button will occur. – galbru Jun 14 '13 at 20:32
  • @Mr.Bean I've added a Download link at the bottom of the post. Get it and try it for yourself. Also read the message I've left below the link. The example has `Button`'s which when clicked will hide the `ListBox`. If you see the caret blinking in the `TextBox` when you click elsewhere, it means the `Focus` is still in the `TextBox` and you can't expect the `ListBox` to disappear. `ListBox` will only disappear when the `TextBox` loses focus which is what your question stated. – Viv Jun 14 '13 at 23:13