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.
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:
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.