Изменить шаблон списка на событие потерянного фокуса в WPF
Я хочу представить список с TextBlocks в качестве элементов. Когда пользователь щелкает / выбирает элемент, он превращается в TextBox для редактирования. Как только элементы управления теряют фокус, элемент снова превращается в TextBlock.
Следующий XAML почти работает в том, что TextBlock превращается в TextBox, когда он выбран. Он также возвращается к TextBlock, если я выбираю другой элемент в списке. Проблема в том, что, если я перехожу из списка (в данном случае в текстовое поле "Добавить новый"), элемент списка остается в виде текстового поля.
Вопрос ( WPF ListViewItem потерял фокус события - Как попасть на событие?) Выглядел многообещающим, но я не могу заставить его работать. Я попытался использовать свойство IsFocused, но тогда я не смог отредактировать текстовое поле, потому что, когда я попал в текстовое поле, элемент listbox терял фокус и, таким образом, возвращался к TextBlock, прежде чем у меня была возможность редактировать текст.
Как я могу заставить TextBox вернуться к TextBlock, если список / элемент теряет фокус?
(Любая другая реализация, которая достигает цели, также приветствуется)
<Window x:Class="MyView.MainWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Title="MainWindow1" Height="300" Width="200">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="SelectedTemplate">
<TextBox Text="{Binding Name, Mode=TwoWay}" />
</DataTemplate>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel >
<ListBox ItemsSource="{Binding Departments}" HorizontalContentAlignment="Stretch"
ItemContainerStyle="{StaticResource ContainerStyle}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding NewDepartmentName, Mode=TwoWay}" />
<Button Grid.Column="1" Width="50" Content="Add" Command="{Binding Path=AddNewDepartmentCommand}" />
</Grid>
</StackPanel>
</Window>
2 ответа
Это не отвечает на ваш вопрос, но дает альтернативное решение, делая текстовое поле похожим на текстовый блок, когда элемент списка не выбран:
<Page.Resources>
<ResourceDictionary>
<Style x:Key="ListBoxSelectableTextBox" 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>
</ResourceDictionary>
</Page.Resources>
<Grid>
<ListBox ItemsSource="{Binding Departments}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Margin="5" Style="{StaticResource ListBoxSelectableTextBox}" Text="{Binding Name}" BorderBrush="{x:Null}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Есть много способов сделать это:
- Выше ответ
- Создайте стиль TextBox на основе TextBoxBase таким образом, чтобы при отключении он делал TextBox похожим на TextBlock, устанавливая BorderThickness="0", Background="transparent"
- Сделайте так, чтобы TextBlock и TextBox были в каждом ListViewItem, и используя вышеупомянутую технику ответа, скрывайте и показывайте TextBlock/TextBox с одобрением