我的问题似乎很简单,但我找不到解决这个问题的方法。所以,我在这里。
这是我的代码。
<TextBox CharacterCasing="Upper">
<TextBox.Text>
<Binding Path="nome" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<ValidationRules:IsNotNull/>
<ValidationRules:MyStringLengthValidationRule Length="45"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
我正在使用bindgroup进行提交并取消我的编辑。但是,当我使用UpdateSourceTrigger="PropertyChanged"
时,命令BindingGroup.CancelEdit()
不起作用。为什么呢?
我无法删除UpdateSourceTrigger="PropertyChanged"
,因为ValidationRules
可以在文本更改时发挥作用。
答案 0 :(得分:2)
当将目标值(在这种情况下为TextBox.Text
)分配给源(在本例中为viewmodel属性)时,将应用验证规则。 BindingGroup.CancelEdit()
清除错误状态并将源值复制到目标属性。
当您在UpdateSourceTrigger="PropertyChanged"
TextBox.Text
上设置Binding
时,在文本框中的每次击键时,Binding
都会在TextBox.Text
上运行验证,如果它通过验证,它将目标值复制到source属性。这意味着它会将TextBox.Text
复制到yourViewModel.nome
。
例如,假设yourViewModel.nome
最初为空。
用户在文本框中单击并键入“Arnold”。用户输入时yourViewModel.nome
更新六次,每个字符一次。
用户点击Cancel
按钮,这会导致BindingGroup.CancelEdit()
被调用。
BindingGroup.CancelEdit()
按照设计行事,将yourViewModel.nome
的当前值(字符串"Arnold"
)复制到TextBox.Text
。
这就是你所看到的问题。
使用BindingGroup
,验证是提交。如果字段经过验证并通过验证,则会提交。一旦你承诺,取消就太晚了。
如果您想要阻止验证并一起验证/提交一组字段,那么您使用BindingGroup
和UpdateSourceTrigger="Explicit"
,这会导致验证/提交仅在BindingGroup.CommitEdit()
上发生,或当你打电话给UpdateSource() on the
Binding`时:
myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
如果您想要在没有提交的情况下进行验证,那么您将不得不做一些不同的事情。
最简单,最直接的事情是在绑定上设置UpdateSourceTrigger="Explicit"
,并在文本框上处理TextChanged
:
XAML
<TextBox CharacterCasing="Upper" TextChanged="anyValidatedTextBox_TextChanged">
<TextBox.Text>
<Binding Path="nome" UpdateSourceTrigger="Explicit" Mode="TwoWay">
<Binding.ValidationRules>
<ValidationRules:IsNotNull/>
<ValidationRules:MyStringLengthValidationRule Length="45"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
代码隐藏
private void anyValidatedTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
(sender as TextBox)
.GetBindingExpression(TextBox.TextProperty)
.ValidateWithoutUpdate();
}
或者您可以在不更新的情况下进行整个BindingGroup
验证:
private void anyValidatedTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
myFormStackPanel.BindingGroup.ValidateWithoutUpdate();
}
更普遍的做法,即更正统的MVVM,就是编写一个执行相同操作的行为。
using System;
using System.ComponentModel;
using System.Windows;
namespace HollowEarth.Behaviors
{
public static class Validation
{
#region Validation.OnPropertyChanged Attached Property
public static DependencyProperty GetOnPropertyChanged(FrameworkElement obj)
{
return (DependencyProperty)obj.GetValue(OnPropertyChangedProperty);
}
public static void SetOnPropertyChanged(FrameworkElement obj, DependencyProperty value)
{
obj.SetValue(OnPropertyChangedProperty, value);
}
public static readonly DependencyProperty OnPropertyChangedProperty =
DependencyProperty.RegisterAttached("OnPropertyChanged", typeof(DependencyProperty), typeof(Validation),
new PropertyMetadata(null, OnPropertyChanged_PropertyChanged));
private static void OnPropertyChanged_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = d as FrameworkElement;
if (e.OldValue != null)
{
DependencyPropertyDescriptor.
FromProperty(e.OldValue as DependencyProperty, obj.GetType())
.RemoveValueChanged(obj, ValidateHandler);
}
if (e.NewValue != null)
{
DependencyPropertyDescriptor.
FromProperty(e.NewValue as DependencyProperty, obj.GetType())
.AddValueChanged(obj, ValidateHandler);
}
}
static void ValidateHandler(object sender, EventArgs args)
{
var fe = (FrameworkElement)sender;
var dprop = GetOnPropertyChanged(fe);
fe.GetBindingExpression(dprop).ValidateWithoutUpdate();
}
#endregion Validation.OnPropertyChanged Attached Property
}
}
XAML:
<TextBox
xmlns:hb="clr-namespace:HollowEarth.Behaviors"
CharacterCasing="Upper"
hb:Validation.OnPropertyChanged="{x:Static TextBox.TextProperty}"
>
<TextBox.Text>
<Binding Path="nome" UpdateSourceTrigger="Explicit" Mode="TwoWay">
<Binding.ValidationRules>
<ValidationRules:IsNotNull/>
<ValidationRules:MyStringLengthValidationRule Length="45"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
我宁愿将此行为应用于BindingGroup
或BindingGroup
的所有者,而不是应用于单个字段,但当我尝试使用BindingGroup.BindingExpressions
和BindingGroup.Items
时在应用它们时都是空的。 BindingGroup
没有事件,其集合没有事件。我打赌你可以对BindingGroup
所有者的行为采取行动,你可以在LayoutUpdated
上挂钩,但我的注意力开始徘徊。我会把它作为学生的练习。
作为进一步的练习,您可以复制并粘贴我的代码,甚至无需阅读。这就是我的工作,十分之九。