У меня есть список, в котором отображаются названия разделов справки, которые можно добавить, и названия тем, которые можно изменить. Первоначально это было просто отображение строк, но чтобы заставить работать встроенное редактирование, я изменил его, чтобы использовать пользовательский тип, состоящий из строки и свойства InEdit
, чтобы пользовательский интерфейс мог определять, отображать ли TextBlock
или TextBox
:
XAML:
<ListBox ItemsSource="{Binding HelpTopics, Mode=TwoWay}"
SelectedValuePath="Description"
SelectedValue="{Binding SelectedPageId, Mode=TwoWay}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Description, Mode=TwoWay}"
VerticalAlignment="Center"
MouseLeftButtonUp="TopicTextBlock_MouseLeftButtonUp"
Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=contra}"/>
<TextBox Text="{Binding Description, Mode=TwoWay}"
Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=pro}"
LostFocus="EditTopicTextBox_LostFocus"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Margin="5" Content="Add Topic" Command="{Binding AddTopicCommand}"/>
HelpTopics
является ObservableCollection<EditableHelpTopic>
.
SelectedPageId
является string
.
boolToVisibilityConverter
- это конвертер, который делает то, что говорит.
Что работает:
- Добавление темы создает новый элемент, добавляет его в список и переводит его в режим редактирования.
- Двойной щелчок по существующему элементу переводит этот элемент в режим редактирования, устанавливает фокус на
TextBox
и выделяет весь текст, чтобы его можно было перезаписать.
- Когда
TextBox
теряет фокус, редактирование сохраняется, и дисплей возвращается к TextBlock
.
Что не работает:
- При добавлении новой темы
TextBox
должен иметь фокус и выделенный текст, чтобы пользователь мог ввести новое имя.
Так что мой вопрос есть ли в коде точка или событие, где я знаю, что TextBox
был создан и видим, чтобы я мог установить фокус и выбрать его содержимое. Я пытался подключиться к событию SelectionChanged
, но когда это происходит, TextBox
еще не отображалось. Я также добавил событие к методу OnAddTopicExecute
в модели представления, которое я обработал в представлении, но опять-таки оно сработало до того, как стал видимым TextBox
.
Ниже приведен код, который поддерживает вышеуказанный XAML. Я пытался сократить его, но, похоже, его все еще много, так что вы можете пропустить это, если вам не интересно;)
Код:
private DateTime lastClickTime = DateTime.MinValue;
private Point lastClickPosition;
private void TopicTextBlock_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
UIElement element = sender as UIElement;
if ((DateTime.Now - this.lastClickTime).TotalMilliseconds > 300)
{
this.lastClickPosition = e.GetPosition(element);
this.lastClickTime = DateTime.Now;
}
else
{
Point position = e.GetPosition(element);
if (Math.Abs(this.lastClickPosition.X - position.X) < 4 && Math.Abs(this.lastClickPosition.Y - position.Y) < 4)
{
var textBlock = sender as TextBlock;
var editableHelpTopic = textBlock.DataContext as EditableHelpTopic;
editableHelpTopic.InEdit = true;
var parent = textBlock.Parent as Grid;
TextBox textBox = parent.Children.First(c => c.GetType() == typeof(TextBox)) as TextBox;
textBox.Focus();
textBox.SelectAll();
}
}
}
private void EditTopicTextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = sender as TextBox;
var editableHelpTopic = textBox.DataContext as EditableHelpTopic;
editableHelpTopic.InEdit = false;
if (!textBox.Text.Equals(editableHelpTopic.Description))
{
this.editViewModel.RenameTopic(textBox.Text);
}
}
Просмотр модели:
public EditViewModel()
{
...
this.AddTopicCommand = new DelegateCommand(this.OnAddTopicExecute, this.OnAddTopicCanExecute);
...
}
где DelegateCommand
- реализация ICommand
.
private void OnAddTopicExecute(object parameter)
{
var newTopic = new EditableHelpTopic
{
Description = "NewTopic",
InEdit = true
};
this.HelpTopics.Add(newTopic);
this.SelectedPageId = newTopic.Description;
}
Определения:
public class EditableHelpTopic : INotifyPropertyChanged
{
public bool InEdit { ... }
public string Description { ... }
}