使用MVVM模式强制更新有关验证错误的视图

时间:2010-07-18 04:43:37

标签: wpf binding

我有问题: 我在窗体上有一些控件(复选框,组合框,滑块,文本框)。它们的值绑定到视图模型的不同属性 当视图模型的属性具有特定值时,I 希望这些控件“固定”(显示错误信息并将它们设置为某个固定值(例如:当用户尝试检查时,复选框未选中,滑块设置为某个值,组合的选定项目是列表中的第二项)。 我是这样做的(文本框的简化示例): 在视图中:

            <TextBox 
                Text="{Binding ViewModelProperty, 
                               NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, 
                               ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
                />

在视图模型中: 该属性定义如下:

String _ViewModelProperty;
public String ViewModelProperty
{
    get
    {
        return _ViewModelProperty;
    }
    set
    {

        _ViewModelProperty = value;
        OnPropertyChanged("ViewModelProperty");
    }
}

和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;
    }
}

这适用于复选框,但对于所有其他控件,它的功能如下:用户设置“错误”值,显示错误消息然后,而不是使用固定值更新控件,仍然显示错误的值(它不再与视图模型同步)。

我无法弄清楚如何强制更新控件的值。

提前谢谢。

3 个答案:

答案 0 :(得分:0)

您可以将要修复的控件的IsEnabled属性绑定到ViewModel上的一组属性,例如CanUserChangeSlider。

<Slider IsEnabled={Binding CanUserChangeSlider} ... />

所以在Comboboxes绑定属性的setter中:

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
  }
}

答案 1 :(得分:0)

强制重新绑定的方法是根据需要调用BindingExpression.UpdateTarget()BindingExpression.UpdateSource()

当然,您不希望在视图模型中使用它。

由于我将视图模型注入到视图中,并在视图构造函数中将它们设置为DataContext,因此我会执行以下操作:

  • 声明在强制数据时将从属性设置器调用或引发的视图模型上的委托或事件
  • 在视图构造函数中,将处理程序附加到委托,该委托将调用上述相应的更新方法(同样,覆盖Dispose()并删除处理程序)

基本上,只要在强制数据时引发事件,并传递视图需要重新绑定到视图模型的数据。

这是我的头脑,所以我还没有确定委托签名中可能需要的确切参数,也没有计算处理程序与所有字段一起使用的程度。不过,这可能是一个起点。

答案 2 :(得分:0)

我不使用IsEnabled属性,因为这些是要求:没有禁用,只有在设置“无效”值时才显示消息。
其他要求不是将视图模型注入到视图中......我们有一些“工作空间”类将视图与视图模型链接起来,因此没有视图知道附加到它的视图模型实例。当然,可以从工作区进行注射......我试过这个并且似乎仍然不起作用 但这不是任何其他优雅和MVVM-ish方法吗? 我准备了一个非常简单的例子来说明我的问题 我有2个文本框,绑定到视图模型中的相同属性:

<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>

视图模型具有IDataErrorInfo实现:

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;

    }
}

最初,值为“1000” 如果我在一个文本框中添加“0”,则显示消息,另一个文本框正确更新为“1000”,但聚焦文本框的值仍为“10000”。
我觉得我在这里想念一些必要的东西。

露西亚