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>