Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 使用MVVM模式在验证错误时强制更新视图_Wpf_Binding - Fatal编程技术网

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;

    }
}