我正在创建一个包含多个文本框的WPF窗口,当用户按下“确定”按钮时,我希望所有文本框都被评估为非空白。 我知道我必须使用TextBoxes和'Explicit'的'UpdateSourceTrigger',但我是否需要为每个人调用'UpdateSource()'? e.g。
<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();
答案 0 :(得分:5)
如果您使用Explicit
,则需要致电UpdateSource
。
我不确定这是否是您尝试做的最佳方法,我实际上从不使用Explicit
,如果我不希望更改应用,我宁愿绑定到对象的副本马上,或者如果要取消编辑,我会存储副本并将所有内容还原。
答案 1 :(得分:4)
另一种方法是将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”更改时被调用。在索引器主体中,您可以检查值是否为空并返回错误字符串。如果错误字符串非空,则用户在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"/>
答案 2 :(得分:2)
使用UpdateSourceTrigger = Explicit有一些很好的理由,而不是其他值。想象一下,您必须检查输入的值是否唯一,这将通过读取数据库来完成。这可能需要一些时间,即使0.3秒也是不可接受的。使用PropertyChanged时,每次用户按下键时都会执行此数据库检查,这会使用户界面无法响应。如果UpdateSourceTrigger = LostFocus并且用户将在控件之间快速切换(如果您按住Tab,控件之间存在闪电般的快速循环),则会发生同样的事情。因此,我们的目标是在关键时刻(通常在保存数据之前)立即验证所有内容。这种方法需要最少的代码,这会将数据从视图推送到视图模型并强制验证。代码背后没有验证代码或其他应用程序逻辑,因此MVVM纯粹主义者可以相对平静。我在VB.NET中创建了功能完备的示例,它使用Caliburn.Micro进行MVVM和IoC。您可以在此处下载:https://drive.google.com/file/d/0BzdqT0dfGkO3OW5hcjdBOWNWR2M
答案 3 :(得分:-1)
将其设置为UpdateSourceTrigger=PropertyChanged
会更简单,但每次值更改时(每输入一个字母)都会更新基础变量