使用 WPF 创建搜索框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17044789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:59:02  来源:igfitidea点击:

Creating a search box using WPF

c#wpfeventscontrolssearch-box

提问by Mr. Bean

I'm trying to create a search box with the controls TextBoxand ListBox. When I'm on the TextBoxstarting to type an event handler GotFocusopen the ListBox. I want the ListBoxto be closed when the TextBoxnot on focus. I tried to use the LostFocusevent in the TextBox, but it didn't work.

我正在尝试使用控件TextBoxListBox. 当我TextBox开始键入事件处理程序时,GotFocus打开ListBox. 我希望在未聚焦ListBox时关闭TextBox。我试图在 中使用该LostFocus事件TextBox,但没有奏效。

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 MouseDownevent in the Rectanglecontrol is used to get the TextBoxout of focus, but it isn't working.

控件中的MouseDown事件Rectangle用于获取TextBox焦点,但它不起作用。

回答by Viv

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 ListBoxis still holding the space it resides in. if we instead toggle Visibilityto Collapsed, every-time the ListBoxbecomes Visibleother control's are going to start moving to accomodate that.

然而,在上述方法中,ListBox目前仍持有它驻留在的空间。如果我们不是切换VisibilityCollapsed,每一次的ListBox成为Visible其他控件的将开始移动,以适应这一点。

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 Triggeris set based on the TextBoxhaving / losing focus. IF you click somewhere that does not take focus, then you will not see the Popup(ListBox) disappear.

请记住,Trigger是基于TextBox拥有/失去焦点而设置的。如果您单击未获得焦点的地方,则您不会看到Popup( ListBox) 消失。

回答by Sargis Tovmasyan

XAML:

XAML:

      <Border Grid.Row="0" BorderBrush="Black" BorderThickness="1">
         <Grid >
            <Grid>
               <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="*"/>
                  <ColumnDefinition Width="Auto"/>
               </Grid.ColumnDefinitions>

               <TextBox Grid.Column="0" BorderThickness="0"
                        BorderBrush="Transparent"/>
               <Button Grid.Column="1" Background="Transparent" BorderThickness="0"
                       BorderBrush="Transparent">
                  <Button.Content>
                     <Image Source="../Resources/$YOUR_SEARCH_ICON"></Image>
                  </Button.Content>
               </Button>
            </Grid>
         </Grid>
     </Border>

Then process listView(or what type of view you have) to only show items that contains search result.

然后处理 listView(或您拥有的视图类型)以仅显示包含搜索结果的项目。