Выберите ListBoxItem, если TextBox в ItemTemplate получает фокус
Я добавил 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 ответа
Если у вас есть несколько экземпляров ListBox
тогда вы можете рассмотреть возможность использования вашего собственного списка (получая его из ListBox
). Смотрите объяснение здесь.
Или используйте этот хак, если у вас есть только 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
(что на самом деле круто, по мне).
Вы можете вызвать на имущество 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>
У меня была ситуация, когда при выборе элемента списка менялся его макет, поэтому элемент управления мог отойти от курсора до отпускания кнопки мыши. Я не нашел лучшего решения, чем использовать небольшую задержку в раскадровке, если я хочу сохранить все в xaml.
Важнее, GotKeyboardFocus
кажется, работает лучше, чем IsKeyboardFocusWithin
для повторного выбора.
<EventTrigger RoutedEvent="GotKeyboardFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
<DiscreteBooleanKeyFrame KeyTime="00:00:00.3" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>