У меня есть TabControl, который привязывает данные к списку. (Два элемента данных в списке)
TabControl имеет DataTemplate, который содержит два элемента управления TextBox, привязанных к двум строковым свойствам в моем классе данных.
Если я наберу какой-нибудь текст в Textbox1 на первой вкладке, а затем нажму на Tab2, обновление источника данных не будет выполнено, и изменение будет потеряно.
Это потому, что LostFocus на самом деле не запускается для TextBox1 (он находится на TextBox2, потому что переход на вкладку 2 автоматически фокусирует TextBox1), и я считаю, что это происходит из-за того, что каждая вкладка использует одни и те же текстовые поля из шаблона и просто меняет DataContext на вкладке переключатели.
Здесь могут помочь два события: PreviewLostKeyboardFocus и DataContextChanged
У обоих по-прежнему есть напечатанный текст в TextBox.
Существует также давняя проблема кнопки Сохранить на панели инструментов, которая не фокусируется.
Мне кажется, что, возможно, класс Binding должен прослушивать PreviousLostKeyboardFocus, а не LostFocus, который, кажется, срабатывает в обоих вышеописанных сценариях.
Как вы, ребята, решаете эти проблемы?
Aos, какие способы доступны для использования события PreviewLostKeyboardFocus в Update Source?
(Я думаю, что что-то вроде контейнера верхнего уровня наблюдает за этим событием, проверяет, есть ли привязка к OriginalSource с помощью LostFocus UpdateSourceTrigger и трюки / форсирует привязку для обновления источника - но я новичок в Wpf и могут быть и другие соображения, о которых я не задумывался)
Вот пример приложения ...
<Window x:Class="BindingFocusTabIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="398" Width="731" >
<Grid>
<TabControl Height="267" HorizontalAlignment="Left" Margin="31,36,0,0" Name="tabControl1" VerticalAlignment="Top" Width="472" ItemsSource="{Binding}">
<TabControl.ContentTemplate>
<DataTemplate>
<StackPanel>
<TextBox Margin="3" Name="TextBox1" Text="{Binding Text1}" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" DataContextChanged="TextBox_DataContextChanged"/>
<TextBox Margin="3" Name="TextBox2" Text="{Binding Text2}" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" DataContextChanged="TextBox_DataContextChanged"/>
</StackPanel>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<GroupBox Header="List item 1" Height="115" HorizontalAlignment="Left" Margin="509,50,0,0" Name="groupBox1" VerticalAlignment="Top" Width="188">
<Grid >
<TextBox Height="23" HorizontalAlignment="Left" Margin="28,21,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=[0].Text1}" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="28,50,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" Text="{Binding Path=[0].Text2}"/>
</Grid>
</GroupBox>
<GroupBox Header="List item 2" Height="115" HorizontalAlignment="Left" Margin="509,184,0,0" Name="groupBox2" VerticalAlignment="Top" Width="188">
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="28,21,0,0" Name="textBox3" VerticalAlignment="Top" Width="120" Text="{Binding Path=[1].Text1}" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="28,50,0,0" Name="textBox4" VerticalAlignment="Top" Width="120" Text="{Binding Path=[1].Text2}"/>
</Grid>
</GroupBox>
<ToolBar Height="26" HorizontalAlignment="Left" Margin="54,3,0,0" Name="toolBar1" VerticalAlignment="Top" Width="200">
<Button>Save</Button>
</ToolBar>
</Grid>
и его код
using System;
с использованием System.Collections.Generic;
использование System.Diagnostics;
используя System.Windows;
использование System.Windows.Controls;
используя System.Windows.Input;
namespace BindingFocusTabIssue
{
открытый частичный класс MainWindow: Window
{
public MainWindow ()
{
InitializeComponent ();
DataContext = new List<DataClass>
{
new DataClass { Name="One"},
new DataClass { Name="Two"},
};
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
var textBox = (TextBox) e.Source;
Debug.WriteLine(textBox.Name + "_GotFocus and Text='" + textBox.Text + "'");
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = (TextBox) e.Source;
Debug.WriteLine(textBox.Name + "_LostFocus and Text='" + textBox.Text + "'");
}
private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var textBox = (TextBox) e.Source;
Debug.WriteLine(textBox.Name + "_PreviewLostKeyboardFocus and Text='" + textBox.Text + "'");
}
private void TextBox_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var textBox = (TextBox) sender;
Debug.WriteLine(textBox.Name + "_DataContextChanged and Text='" + textBox.Text + "'");
}
}
public class DataClass
{
public string Name { get; set; }
public string Text1 { get; set; }
public string Text2 { get; set; }
public override string ToString()
{
return Name;
}
}
}