wpf 更新源触发器=显式

knpiaxh1  于 2022-11-18  发布在  其他
关注(0)|答案(5)|浏览(180)

我正在创建一个具有多个文本框的WPF窗口,当用户按“确定”按钮时,我希望所有文本框都被评估为非空。我知道我必须使用“UpdateSourceTrigger”为“Explicit”的文本框,但我是否需要为每个文本框调用“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();
iqjalb3h

iqjalb3h1#

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

x33g5p2x

x33g5p2x2#

另一种方法是将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;
        }
    }
}

假设您的其中一个TextBox系结至如上所述的'MyProperty'。索引子是在IDataErrorInfo中实作,并在'MyProperty'变更时呼叫。在索引子主体中,您可以执行值是否为空的检查,并传回错误字串。如果错误字串非Null,用户在TextBox上得到一个漂亮的装饰器作为视觉提示。
如果您使用上面编码的两个接口并使用UpdateSourceTrigger=PropertyChanged,那么所有这些都是免费的。
TextBox的XAML将是...

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

cdmah0mi3#

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

t40tm48m

t40tm48m4#

我编写了一些扩展,它们可能会使更新源代码更方便:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;

internal static class EXT_Binding
{
    internal static void _UpdateSource(this FrameworkElement element, DependencyProperty dp)
    {
        BindingExpression be = element.GetBindingExpression(dp: dp);
        be?.UpdateSource();
    }

    internal static void _UpdateSource(this DependencyProperty dp, FrameworkElement element)
    {
        BindingExpression be = element.GetBindingExpression(dp: dp);
        be?.UpdateSource();
    }

    internal static void _UpdateSources(this FrameworkElement element, List<DependencyProperty> dps)
    {
        foreach (var dp in dps)
        {
            BindingExpression be = element.GetBindingExpression(dp: dp);
            be?.UpdateSource();
        }
    }

    internal static void _UpdateSources(this FrameworkElement element, params DependencyProperty[] dps)
    {
        foreach (var dp in dps)
        {
            BindingExpression be = element.GetBindingExpression(dp: dp);
            be?.UpdateSource();
        }
    }
}

其例如然后可以照此使用,

this._UpdateSources(WidthProperty, HeightProperty, LeftProperty, TopProperty);
lbsnaicq

lbsnaicq5#

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

相关问题