【问题标题】:Select ListBoxItem if TextBox in ItemTemplate gets focus如果 ItemTemplate 中的 TextBox 获得焦点,则选择 ListBoxItem
【发布时间】:2010-02-03 12:49:26
【问题描述】:

我已将 DataTemplate 添加到 ListBox 类以将我的收藏绑定到:

<ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276"
         SelectionChanged="lstEmails_SelectionChanged">
    <ListBox.ItemTemplate> 
        <DataTemplate> 
            <StackPanel Orientation="Horizontal"> 
                <Label Visibility="Hidden" Content="{Binding ID}"></Label> 
                <TextBox Width="200"  Text="{Binding EmailAddress}"></TextBox> 
            </StackPanel> 
        </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

这正是我想要的。虽然当我点击TextBox 时,ListBox 不会自动将关联的ListItem 设置为Selected。我可以在代码中做到这一点,但我更愿意将它用作一个组件(那就不足为奇了)。

关于如何实现这一点的任何想法?


这似乎不起作用,它不会让我点击任何东西。我是不是错过了什么。这是我的新 XAML。

<UserControl.Resources> 
    <!--<TextBox x:Key="TB" x:Name="TextBoxInsideListBoxItemTemplate"> 
        <TextBox.Style>--> 
            <Style TargetType="{x:Type TextBox}"> 
                <Setter Property="IsHitTestVisible" Value="False" /> 
                <Style.Triggers> 
                    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}" 
                                                     Value="True"> 
                        <Setter Property="IsHitTestVisible" Value="True" /> 
                    </DataTrigger> 
                </Style.Triggers> 
            </Style> 
        <!--</TextBox.Style> 
    </TextBox>--> 
</UserControl.Resources> 
<Grid> 
    <ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276" SelectionChanged="lstEmails_SelectionChanged">
        <ListBox.ItemTemplate> 
            <DataTemplate> 
                <StackPanel Orientation="Horizontal"> 
                    <!--<Label Visibility="Hidden" Content="{Binding ID}"></Label>--> 
                    <TextBox Width="220" Text="{Binding EmailAddress}" > 
                    </TextBox> 
                    <!--<TextBox Width="220" Text="{Binding EmailAddress}" GotFocus="TextBox_GotFocus"></TextBox>-->
                </StackPanel> 
            </DataTemplate> 
        </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Width="20" Margin="12,0,0,12" Name="btnAdd" VerticalAlignment="Bottom" Click="btnAdd_Click" Height="23" HorizontalAlignment="Left">+</Button>
    <Button Width="20" HorizontalAlignment="Left" Margin="30,0,0,12" Name="btnRemove" VerticalAlignment="Bottom" Click="btnRemove_Click" Height="23">-</Button>
    <Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12" Name="btnApply" VerticalAlignment="Bottom" Width="49" Click="btnApply_Click">Apply</Button>
</Grid>

我认为点击两次是很好的功能。

【问题讨论】:

    标签: wpf listbox datatemplate selection listboxitem


    【解决方案1】:

    您可以在ItemContainerStyle 中的属性IsKeyboardFocusWithin 上触发并将IsSelected 设置为true

    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
                                    <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
                                </BooleanAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
    

    您也可以使用Setter 代替单帧动画,但是一旦焦点离开ListBox,选择将再次丢失:

    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">
                    <Setter Property="IsSelected" Value="True"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
    

    【讨论】:

    • 太棒了!今天救了我!
    • 这是一个很好的解决方案,但它不能很好地与扩展和多选模式相结合。
    【解决方案2】:

    如果您有多个ListBox 实例,那么您可以考虑使用您的自定义列表框(通过从ListBox 派生它)。见the explanation here


    或者,如果您只有 1 个(或只有少数)这样的 ListBox 并且不想为此创建单独的类,请使用此 hack

    <TextBox x:Name="TextBoxInsideListBoxItemTemplate" ... >
    
        <TextBox.Style>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="IsHitTestVisible" Value="False" />
                <Style.Triggers>
                    <DataTrigger
                            Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}"
                            Value="True">
                        <Setter Property="IsHitTestVisible" Value="True" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    
    </TextBox>
    

    请注意,您必须再次单击才能编辑 TextBox 中的文本(在我看来这真的很酷)。

    【讨论】:

      【解决方案3】:

      我遇到过选择列表框项会改变其布局的情况,因此在释放鼠标按钮之前控件可能已从光标移开。如果我想将所有内容保存在 xaml 中,我没有找到比在情节提要中稍微延迟更好的解决方案。

      更重要的是,GotKeyboardFocus 似乎比IsKeyboardFocusWithin 更适合重复选择。

      <EventTrigger RoutedEvent="GotKeyboardFocus">
          <BeginStoryboard>
              <Storyboard>
                  <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
                      <DiscreteBooleanKeyFrame KeyTime="00:00:00.3" Value="True"/>
                  </BooleanAnimationUsingKeyFrames>
              </Storyboard>
          </BeginStoryboard>
      </EventTrigger>
      

      【讨论】:

        猜你喜欢
        • 2011-06-08
        • 1970-01-01
        • 2012-07-06
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 2021-10-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多