Wpf 使用MVVM模式在验证错误时强制更新视图
我有个问题: 我在表单上有一些控件(复选框、组合框、滑块、文本框)。它们的值绑定到视图模型的不同属性。Wpf 使用MVVM模式在验证错误时强制更新视图,wpf,binding,Wpf,Binding,我有个问题: 我在表单上有一些控件(复选框、组合框、滑块、文本框)。它们的值绑定到视图模型的不同属性。 当视图模型的属性具有某个值时,I 希望这些控件“固定”(显示一条错误消息,并将它们设置为某个固定值(例如:当用户尝试选中复选框时,复选框未选中,滑块设置为某个值,组合的选定项是列表中的第二项)。 我是这样做的(文本框的简化示例): 他认为: <TextBox Text="{Binding ViewModelProperty,
当视图模型的属性具有某个值时,I 希望这些控件“固定”(显示一条错误消息,并将它们设置为某个固定值(例如:当用户尝试选中复选框时,复选框未选中,滑块设置为某个值,组合的选定项是列表中的第二项)。 我是这样做的(文本框的简化示例): 他认为:
<TextBox
Text="{Binding ViewModelProperty,
NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
以及IDataErrorInfo的实施:
String IDataErrorInfo.this[String propertyName]
{
get
{
String error = null;
if (propertyName == "ViewModelProperty")
{
if (ViewModelProperty != "FixedValue")
{
error = DisplayMessage("You can only set a fixed value here");
ViewModelProperty= "FixedValue";
}
}
return error;
}
}
这对于复选框很有效,但对于所有其他控件,它的功能如下:用户设置“错误”值,显示错误消息,然后,不使用固定值更新控件,仍然显示错误值(不再与视图模型同步)
我不知道如何强制更新控件的值
提前感谢。您可以将要修复的控件的IsEnabled属性绑定到ViewModel上的一组属性,例如CanUserChangeSlider
<Slider IsEnabled={Binding CanUserChangeSlider} ... />
强制重新绑定的方法是根据需要调用
BindingExpression.UpdateTarget()
或BindingExpression.UpdateSource()
当然,您不希望在视图模型中出现这种情况
由于我将视图模型注入到视图中,并将它们设置为视图构造函数中的DataContext
,因此我将执行以下操作:
- 在视图模型上声明一个委托或事件,该委托或事件将在强制数据时从属性设置器调用或引发
- 在视图构造函数中,将处理程序附加到将调用上述适当更新方法的委托(另外,重写
并删除该处理程序)Dispose()
这是我不知道的,所以我还没有计算出您在委托签名中可能需要的确切参数,也没有计算出处理程序可以在多大程度上处理您的所有字段。不过,这可能是一个起点。我不使用IsEnabled属性,因为这些是要求:没有禁用,只有messa如果设置了“无效”值,则显示ge。
其他要求是不将视图模型注入视图…我们有一些“工作区”类将视图与视图模型链接起来,因此没有视图知道附加到它的视图模型实例。当然,可以从工作区进行注入…我尝试了这一点,但似乎仍然不起作用。
但是,难道没有其他优雅的MVVM风格的方法可以做到这一点吗? 我准备了一个非常简单的例子来说明我的问题。
我有两个文本框,绑定到视图模型中的相同属性:
<StackPanel>
<Label>First text box</Label>
<TextBox
Text="{Binding Path=Property,
NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
<Label>Second text box</Label>
<TextBox
Text="{Binding Path=Property,
NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
</StackPanel>
最初,该值为“1000”。如果在一个文本框中添加“0”,则会显示消息,另一个文本框将正确更新为“1000”,但焦点文本框的值仍为“10000”。
我觉得我错过了一些重要的东西
Lucia如果控件已修复,您为什么允许用户更改控件中允许的内容?
set
{
// store value in backing store
// RaisePropertyChanged
if (value == true)
{
this.CanUserChangeSlider = false;
// the bound property for slider set to certain value
// the bound property for combobox changed to be a certain value
}
}
<StackPanel>
<Label>First text box</Label>
<TextBox
Text="{Binding Path=Property,
NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
<Label>Second text box</Label>
<TextBox
Text="{Binding Path=Property,
NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
/>
</StackPanel>
public String this[String propertyName]
{
get
{
String error = null;
if (propertyName == "Property")
{
if (Property != "1000")
{
error ="Only value '1000' is accepted here.";
MessageBox.Show(error, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
Property = "1000";
}
}
return error;
}
}