LostFocus 绑定在模板上不起作用

发布于 2024-08-24 22:25:54 字数 4954 浏览 11 评论 0原文

我有一个 TabControl,它将数据绑定到列表。 (列表中的两个数据项) TabControl 有一个 DataTemplate,其中包含两个绑定到我的数据类上的两个字符串属性的 TextBox 控件。

如果我在第一个选项卡上的 Textbox1 上键入一些文本,然后单击 Tab2,则不会对数据源进行任何更新,并且更改会丢失。

这是因为 LostFocus 实际上并未针对 TextBox1 触发(它在 TextBox2 上,因为移动到选项卡 2 自动聚焦 TextBox1),并且我相信这是由于每个选项卡共享模板中的相同 TextBox,而只是更改选项卡开关上的 DataContext。

两个事件可能会有所帮助:PreviewLostKeyboardFocus 和 DataContextChanged 两者仍然可以在文本框中输入文本。

还有一个古老的问题,即工具栏的“保存”按钮无法获得焦点。

在我看来,也许 Binding 类应该监听 PreviousLostKeyboardFocus 而不是 LostFocus,后者似乎在上述两种情况下都会触发。

你们如何解决这些问题?

Aos,有哪些方法可以利用 PreviewLostKeyboardFocus 事件来更新源? (我在想顶级容器会监视此事件,检查 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 的代码隐藏; 使用系统诊断; 使用系统.Windows; 使用 System.Windows.Controls; 使用系统.Windows.输入;

命名空间 BindingFocusTabIssue { 公共部分类 MainWindow : 窗口 { 公共主窗口() { 初始化组件();

        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;
    }
}

}

I have a TabControl that is data bound to a list. (Two data items in the list)
The TabControl has a DataTemplate which contains two TextBox controls bound to two string properties on my data class.

If I type some text on Textbox1 on the first tab and then click onto Tab2, no update is made to the data source and the change is lost.

This is because LostFocus is not actually fired for TextBox1 (it is on TextBox2 because moving to Tab 2 automatically focuses TextBox1) and I believe this is due to each tab sharing the same TextBoxes from the template and just changing the DataContext on tab switches.

Two events may help here: PreviewLostKeyboardFocus and DataContextChanged
Both still have the typed text on the TextBox available.

There is also the age-old problem of a toolbar Save button which doesn't get focus.

It seems to me that maybe the Binding class should be listening to PreviousLostKeyboardFocus rather than LostFocus which seems to fire in both the above scenarios.

How do you guys solve these issues?

Aos, what ways are available to harness the PreviewLostKeyboardFocus event to Update Source?
(I'm thinking something along the lines of a top level container watches this event, checks if there is a Binding on the OriginalSource with a LostFocus UpdateSourceTrigger and tricks/forces the binding to update the source - but I'm new to Wpf and there might be other considerations I haven't thought about)

Here is a sample app...

<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>

and its codebehind

using System;

using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace BindingFocusTabIssue
{
public partial class 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;
    }
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文