Выберите ListBoxItem, если TextBox в ItemTemplate получает фокус - PullRequest
8 голосов
/ 03 февраля 2010

Я добавил 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>

Я думаю, что двойной щелчок - это хорошая функциональность.

Ответы [ 3 ]

9 голосов
/ 26 сентября 2011

Вы можете вызвать свойство IsKeyboardFocusWithin в ItemContainerStyle и установить 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>
5 голосов
/ 03 февраля 2010

Если у вас есть несколько экземпляров ListBox, вы можете рассмотреть возможность использования своего собственного списка (получая его из ListBox). См. объяснение здесь .


Или используйте hack , если у вас есть только 1 (или только небольшое количество) таких ListBox и вы не хотите создавать отдельный класс для этого:

<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 (что, на мой взгляд, действительно здорово).

1 голос
/ 30 августа 2014

У меня была ситуация, когда при выборе элемента списка менялось его расположение, поэтому элемент управления мог отойти от курсора до отпускания кнопки мыши. Я не нашел лучшего решения, чем использовать небольшую задержку в раскадровке, если я хочу сохранить все в xaml.

Что еще более важно, GotKeyboardFocus, кажется, работает лучше, чем IsKeyboardFocusWithin для повторного выбора.

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