WPF: привязка данных TabControl не фиксирует изменения при выборе новой вкладки
У меня есть TabControl, где каждая вкладка и ее содержимое являются привязкой к привязке к ObservableCollection:
<TabControl ItemsSource="{Binding Path=.}">
<TabControl.ContentTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=propertyValue}" />
</DataTemplate>
</TabControl>
</TabControl>
Если бы я нажал на вкладку 1, введите что-то в текстовое поле и нажмите вкладку так, чтобы TextBox потерял фокус, новые данные, которые я ввел в текстовое поле, будут привязаны к элементу ObservableCollection.
Однако, если я ввожу данные в TestBox, а затем сразу же нажимаю на другую вкладку, данные никогда не выполняются. Кроме того, когда я возвращаюсь к данным, он больше не подходит к тому, что я набрал.
Кто-нибудь знает, как заставить данные быть зафиксированными до изменения текущей вкладки?
UPDATE и FIX
Что я сделал, было подключено событие SelectionChanged
:
private void tabData_SelectionChanged(object sender, SelectionChangedEventArgs e) {
theTabControl.Focus();
}
Вызов Focus() на TabControl позволяет TextBox потерять фокус и зафиксировать данные. Я сделал это, потому что у меня есть другие элементы управления, такие как DatePicker, которые демонстрируют подобное поведение. Это своего рода уловка.
Ответы
Ответ 1
Эта проблема хорошо описана здесь: WPF Binding: используйте LostKeyboardFocus вместо LostFocus как UpdateSourceTrigger Очень интересно видеть, что ребята из Microsoft знают о эта проблема в течение нескольких лет, но все еще не исправлена.
Также большое обсуждение здесь: WPF Databind Before Saving
Этот хак работает:
<TabControl SelectionChanged="OnSelectionChanged">
И codebehind:
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (Keyboard.FocusedElement is TextBox)
Keyboard.FocusedElement.RaiseEvent(new RoutedEventArgs(LostFocusEvent));
}
Ответ 2
Если вы выберете новую вкладку, старая будет выгружена из визуального дерева. Я предполагаю, почему изменение не совершается. Вы можете попробовать остановить это поведение или как обходной путь, который вы можете установить UpdateSourceTrigger до PropertyChanged
:
<TextBox Text="{Binding Path=propertyValue, UpdateSourceTrigger="PropertyChanged"}" />
Ответ 3
Это может быть самый аккуратный ответ, если у вас есть другие элементы управления или способы перехода из текстового поля отдельно от элемента управления вкладкой. Если текстовое поле каким-либо образом теряет фокус клавиатуры, оно становится обновленным до потери фокуса.
<TextBox PreviewLostKeyboardFocus="commentTextBox_PreviewLostKeyboardFocus" Name="commentTextBox" Text="{Binding Comment, UpdateSourceTrigger=LostFocus}"/>
и в обработчике событий в коде: -
private void commentTextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
(sender as TextBox).RaiseEvent(new RoutedEventArgs(LostFocusEvent));
}
Это приводит к обновлению "потерянного фокуса клавиатуры" до полноценного события "потерянного фокуса" на этапе предварительного просмотра.
Ответ 4
возможно, вы можете попробовать это
<TabControl ItemsSource="{Binding Path=.}">
<TabControl.ContentTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=propertyValue,UpdateSourceTrigger=LostFocus}" />
</DataTemplate>
</TabControl>