【问题标题】:Ignoring text/value changes due to databinding由于数据绑定而忽略文本/值更改
【发布时间】:2011-10-20 19:38:57
【问题描述】:

当发生数据绑定时,如何忽略对控件的更改?我尝试挂钩各种事件,如 gotfocus、textchanged 和 leavefocus,但如果控件已经具有焦点并且用户“取消”他们的更改,当我重新加载记录并且数据绑定接管时,textchanged 认为用户仍然进行了更改重点是那个控制。调用堆栈为空。是否有任何全局数据绑定事件,例如数据绑定开始和数据绑定结束?我看到我在哪里触发了 OnProperyChanged,但在该调用中,不会发生数据绑定。看起来它正在“排队”并在其他时间运行。

在某一时刻,我打算在我们的视图模型中挂钩属性更改事件,但这意味着在用户离开控件之前,我不会检测到并且无法直观地显示表单已修改。我知道,我知道,我可以更改我的所有绑定,以便在每次更改字符时立即发生绑定,但这会与一些验证案例混淆,因为用户尚未完成输入值。

我真的很喜欢像 TextChangedByUser 这样的事件,无论用户是否使用了键、剪贴板、鼠标剪贴板,以及用户触发的任何东西,它都会触发。

我只是不知道如何区分用户更改和数据绑定更改。

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    我真的很喜欢像 TextChangedByUser 这样的事件 触发用户是否使用了键、剪贴板、鼠标剪贴板等 由用户触发。

    我只是不知道如何区分用户更改和 数据绑定更改。

    不要使用Text.TextChanged 事件来检测用户输入,
    请改用Binding.SourceUpdated 事件。

    或更笼统地说: 不要使用视觉元素的 DP 来检测用户更新,而是使用 Binding.SourceUpdated 事件。

    这是一个路由事件。 在您的绑定中,您必须设置NotifyOnSourceUpdated = true。在UpdateSourceTrigger 的帮助下,您甚至可以在需要通知时进行微调。


    你的 xaml 可能是这样的:
    <Grid x:Name="LayoutRoot" Binding.SourceUpdated="LayoutRoot_SourceUpdated">
        ...
        <TextBox>
            <TextBox.Text>
                <Binding NotifyOnSourceUpdated="True" Path="path" UpdateSourceTrigger="PropertyChanged" >
                </Binding>
            </TextBox.Text>
    </Grid>
    

    您的活动可能是这样的:

    private void LayoutRoot_SourceUpdated(object sender, DataTransferEventArgs e)
    {
        // called every time s.th. changed by user
    }
    

    (因评论而编辑)
    为什么这是检测用户是否以任何方式触发输入的有效方法?
    在给定的示例中,TextBox 的 DataContext 'path' 属性是 source,而 'TextBox.Text' 属性是 target
    [数据绑定概述]http://msdn.microsoft.com/en-us/library/ms752347.aspx
    当绑定初始化并将源值写入“TextBox.Text”属性时,第一次更改 TextBox.Text 属性。因为您不知道绑定发生的确切时间,所以您不能使用 TextBox.Text 属性或其任何事件(例如 TextChanged)来检测用户输入。因此: 不要使用Text.TextChanged 事件来检测用户输入!!!更通用:不要使用视觉元素的 DP 来检测用户更新!!!

    如果用户以任何方式更改可视文本字段的内容,“TextBox.Text”属性会更改(您的目标)。之后,绑定会更新UpdateSourceTrigger 定义的时间。那是触发 SourceUpdated 事件的时间。

    我承认不知道从绑定外部更改绑定源的效果。 但是我有一个完整的类似编辑器的桌面应用程序,可以通过这种方式检测用户的更改,并且运行良好。

    【讨论】:

    • 是的,我已经找到了,虽然这并不是我直接想要的。我正在为绑定对象的 TargetUpdated 事件添加一个事件处理程序。在我的自定义控件中处理的这个事件中,我重置了用于跟踪用户是否正在修改字段的标志。我真正想要的是在任何事件处理程序中能够查询一些告诉我这是否是绑定事件的静态属性。
    • 恕我直言,您真的以错误的方式看待这个问题。您应该考虑按照我建议的方式从 TargetUpdated 迁移到 SourceUpdated 进行重新设计。你会意识到这正是你正在寻找的。 “我真正想要的是在任何事件处理程序中能够查询一些告诉我这是否是绑定事件的静态属性”
    • 我明白你在说什么。我想从技术上讲, sourceupdated 总是会先触发然后再更新目标?我将尝试挂钩 SourceUpdated
    • 由于您的评论,我编辑了帖子。希望有帮助。非常感谢将此帖子标记为“已回答”。 :-)
    • 检测源更改还有另一个问题。例如,当用户按下下一个记录按钮并且我所做的只是更新我的源业务对象属性时,源更改触发,控制目标文本更改触发,但这不是我想要显示/指示的用户更改修改后的记录。
    【解决方案2】:

    您应该更新您的绑定代码以设置以下内容

    {Binding Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
    

    编辑:对不起,我已经监督了你已经知道这一点的事实......在那种情况下,我无能为力:(

    【讨论】:

      【解决方案3】:

      您可以使用UIElement.TextInput event 来检测用户输入。

      请注意,该事件可能已由输入控件本身处理,因此您可能必须使用UIElement.PreviewTextInput event

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 2022-12-07
        • 2015-03-27
        • 2017-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多