wpf UpdateSourceTrigger=显式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8805375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UpdateSourceTrigger=Explicit
提问by Chris Milburn
I'm creating a WPF window with multiple textboxes, when the user presses the OK button I want all the text boxes to be evaluated for being non-blank. I understand that I have to use TextBoxes with 'UpdateSourceTrigger of 'Explicit', but do I need to call 'UpdateSource()' for each of them ? e.g.
我正在创建一个带有多个文本框的 WPF 窗口,当用户按下 OK 按钮时,我希望所有文本框都被评估为非空白。我知道我必须使用带有 '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();
采纳答案by Gayot Fow
An alternative approach can be to set your UpdateSourceTrigger to PropertyChanged.
另一种方法是将您的 UpdateSourceTrigger 设置为 PropertyChanged。
And then inherit your VM from both INotifyPropertyChanged and IDataErrorInfo. Here's an example...
然后从 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;
}
}
}
Assume that one of your TextBoxes is bound to 'MyProperty' as declared above. The indexer is implemented in IDataErrorInfo, and gets called when 'MyProperty' changes. In the indexer body, you can perform a check if the value is empty and return an error string. If the error string is non-null, the user gets a nice adorner on the TextBox as a visual cue. So you are in one shot performing validation and delivering the UI experience.
假设您的 TextBox 之一绑定到上面声明的“MyProperty”。索引器在 IDataErrorInfo 中实现,并在“MyProperty”更改时被调用。在索引器主体中,您可以检查值是否为空并返回错误字符串。如果错误字符串不为空,则用户会在 TextBox 上获得一个漂亮的装饰器作为视觉提示。因此,您可以一次性执行验证并提供 UI 体验。
All of this is for free if you use the two interfaces as coded above and use UpdateSourceTrigger=PropertyChanged. The use of UpdateSourceTrigger = Explicit is massive overkill for providing the validation you described.
如果您使用上面编码的两个接口并使用 UpdateSourceTrigger=PropertyChanged,则所有这些都是免费的。UpdateSourceTrigger = Explicit 的使用对于提供您描述的验证来说是巨大的矫枉过正。
The Xaml for the TextBox would be...
TextBox 的 Xaml 将是...
<TextBox DataContext="{StaticResource Vm}" Text="{Binding MyProperty,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True,
NotifyOnSourceUpdated=True, Mode=TwoWay}" Width="200" Height="25"/>
回答by H.B.
If you use Explicit
you need to call UpdateSource
.
如果您使用Explicit
,则需要调用UpdateSource
.
I am not sure if this is the best approach to what you try to do though, i for one virtually never use Explicit
, i rather bind to a copy of an object if i do not want changes to apply right away, or i store a copy and revert everything back if edits are to be cancelled.
我不确定这是否是您尝试执行的操作的最佳方法,我几乎从未使用过Explicit
,如果我不想立即应用更改,我宁愿绑定到对象的副本,或者我存储一个副本如果要取消编辑,则将所有内容还原。
回答by Ond?ej
There are some good reasons to use UpdateSourceTrigger=Explicit, instead of other values. Imagine that you have to check if entered value is unique, which will be done by reading database. That can take some time, even 0.3 seconds is unacceptable. When using PropertyChanged, this database checking will be performed every time user presses key, which makes user interface extremely unresponsive. Same thing happens if UpdateSourceTrigger=LostFocus and user will be quickly switching between controls (if you hold Tab, there is lightning fast cycling between controls). So our objective is to validate everything at once at key moment (usually before data is saved). This approach will need minimal code behind, which will push data from view to viewmodel and forces validation. There is no validation code or other application logic inside code behind, so MVVM purists can be relatively calm. I created fully functional example in VB.NET, which is using Caliburn.Micro for MVVM and IoC. You can download it here: https://drive.google.com/file/d/0BzdqT0dfGkO3OW5hcjdBOWNWR2M
使用 UpdateSourceTrigger=Explicit 而不是其他值有一些很好的理由。想象一下,您必须检查输入的值是否唯一,这将通过读取数据库来完成。这可能需要一些时间,即使是 0.3 秒也是不可接受的。使用PropertyChanged 时,每次用户按键时都会执行此数据库检查,这使得用户界面非常无响应。如果 UpdateSourceTrigger=LostFocus 并且用户将在控件之间快速切换(如果您按住 Tab,控件之间会有闪电般的快速循环),也会发生同样的事情。所以我们的目标是在关键时刻(通常在保存数据之前)一次验证所有内容。这种方法需要最少的代码,它将数据从视图推送到视图模型并强制验证。代码内部没有验证代码或其他应用程序逻辑,所以MVVM纯粹主义者可以相对冷静。我在 VB.NET 中创建了功能齐全的示例,该示例将 Caliburn.Micro 用于 MVVM 和 IoC。您可以在这里下载:https://drive.google.com/file/d/0BzdqT0dfGkO3OW5hcjdBOWNWR2M
回答by Louis Kottmann
It would be simpler to just set it to UpdateSourceTrigger=PropertyChanged
although it will update the underlying variable each time the value changes (for each letter inputted)
将它设置为更简单,UpdateSourceTrigger=PropertyChanged
尽管每次值更改时它都会更新基础变量(对于输入的每个字母)