【问题标题】:UpdateSourceTrigger=ExplicitUpdateSourceTrigger=显式
【发布时间】:2012-01-10 15:02:43
【问题描述】:

我正在创建一个带有多个文本框的 WPF 窗口,当用户按下“确定”按钮时,我希望所有文本框都被评估为非空白。 我知道我必须使用带有'Explicit'的'UpdateSourceTrigger'的TextBoxes,但我需要为它们中的每一个调用'UpdateSource()'吗? 例如

<TextBox Height="23" 
     HorizontalAlignment="Left" 
     Margin="206,108,0,0" 
     Text="{Binding Path=Definition, UpdateSourceTrigger=Explicit}"
     Name="tbDefinitionFolder" 
     VerticalAlignment="Top" 
     Width="120" />

<TextBox Height="23" 
     HorizontalAlignment="Left" 
     Margin="206,108,0,0" 
     Text="{Binding Path=Release, UpdateSourceTrigger=Explicit}"
     Name="tbReleaseFolder" 
     VerticalAlignment="Top" 
     Width="120" />

...

BindingExpression be = tbDefinitionFolder.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
BindingExpression be2 = tbReleaseFolder.GetBindingExpression(TextBox.TextProperty);
be2.UpdateSource();

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    如果您使用Explicit,则需要致电UpdateSource

    我不确定这是否是您尝试做的最佳方法,我实际上从不使用Explicit,如果我不想立即应用更改,我宁愿绑定到一个对象的副本,或者如果要取消编辑,我会存储一个副本并恢复所有内容。

    【讨论】:

    • 如果你有一个表单,当用户按下“提交”时需要检查多个编辑框(例如汽车保险详细信息表单),你会如何设计它?
    • @ChrisMilburn:我可能会将validation rules 添加到绑定中,然后在实际继续之前查看每个控件是否有效。 Here would be some article on the issue.
    【解决方案2】:

    另一种方法是将 UpdateSourceTrigger 设置为 PropertyChanged。

    然后从 INotifyPropertyChanged 和 IDataErrorInfo 继承您的 VM。这是一个例子......

    public class MyViewModel : INotifyPropertyChanged, IDataErrorInfo
    {
        private string myVar;
        public string MyProperty
        {
            [DebuggerStepThrough]
            get { return myVar; }
            [DebuggerStepThrough]
            set
            {
                if (value != myVar)
                {
                    myVar = value;
                    OnPropertyChanged("MyProperty");
                }
            }
        }
        private void OnPropertyChanged(string prop)
        {
            if(PropertyChanged!=null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(pro));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public string Error
        {
            get { return String.Empty; }
        }
        public string this[string columnName]
        {
            get
            {
                if (columnName == "MyProperty")
                {
                    if (String.IsNullOrEmpty(MyProperty))
                    {
                        return "Should not be blank";
                    }
                }
                return null;
            }
        }
    }
    

    假设您的一个 TextBoxes 绑定到上面声明的“MyProperty”。索引器在 IDataErrorInfo 中实现,并在“MyProperty”更改时被调用。在索引器主体中,您可以检查值是否为空并返回错误字符串。如果错误字符串不为空,则用户会在 TextBox 上获得一个漂亮的装饰器作为视觉提示。因此,您可以一次性执行验证并提供 UI 体验。

    如果您使用上面编码的两个接口并使用 UpdateSourceTrigger=PropertyChanged,所有这些都是免费的。对于提供您描述的验证,使用 UpdateSourceTrigger = Explicit 是非常过分的。

    TextBox 的 Xaml 将是...

     <TextBox DataContext="{StaticResource Vm}" Text="{Binding MyProperty,
                    UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, 
                    NotifyOnSourceUpdated=True, Mode=TwoWay}" Width="200" Height="25"/>
    

    【讨论】:

    • +1 因为这种数据验证应该在 ViewModel 中使用IDataErrorInfo 完成
    • 感谢 Garry Ive 按照您的建议实现了它,我现在遇到的问题是当对话框启动时文本框出现错误,即红色?
    • @Rachel 我不明白为什么他的方法仍在更新源而不调用UpdateSource()
    • @Igor 绑定中的UpdateSourceTrigger=PropertyChanged 告诉绑定在属性更改时更新源。如果你想让它只在你调用UpdateSource()时更新,你需要设置UpdateSourceTrigger=Explicit
    • @Rachel 没错,但在我的示例中,我使用带有文本框模板列的 DataGrid,UpdateSourceTrigger 设置为 Explicit,它仍然会更新失去焦点的源。
    【解决方案3】:

    有一些很好的理由使用 UpdateSourceTrigger=Explicit,而不是其他值。想象一下,您必须检查输入的值是否唯一,这将通过读取数据库来完成。这可能需要一些时间,即使是 0.3 秒也是不可接受的。使用 PropertyChanged 时,每次用户按键时都会执行此数据库检查,这使得用户界面非常无响应。如果 UpdateSourceTrigger=LostFocus 并且用户将在控件之间快速切换,也会发生同样的情况(如果您按住 Tab,则控件之间会出现闪电般的快速循环)。因此,我们的目标是在关键时刻(通常在保存数据之前)一次验证所有内容。这种方法需要最少的代码,它将数据从视图推送到视图模型并强制验证。后面的代码里面没有验证码或者其他应用逻辑,所以MVVM的纯粹主义者可以相对冷静一些。我在 VB.NET 中创建了功能齐全的示例,该示例将 Caliburn.Micro 用于 MVVM 和 IoC。你可以在这里下载:https://drive.google.com/file/d/0BzdqT0dfGkO3OW5hcjdBOWNWR2M

    【讨论】:

      【解决方案4】:

      将其设置为UpdateSourceTrigger=PropertyChanged 会更简单,尽管它会在每次值更改时更新基础变量(对于输入的每个字母)

      【讨论】:

        猜你喜欢
        • 2015-01-06
        • 2011-03-05
        • 2011-08-28
        • 1970-01-01
        • 2011-12-01
        • 2010-11-19
        • 1970-01-01
        • 2011-12-08
        • 1970-01-01
        相关资源
        最近更新 更多