值更改的绑定直接存储在DB中

时间:2010-06-24 11:06:26

标签: wpf data-binding

我正在努力解决我正在尝试添加到我的WPF项目中的一个绑定。 在应用程序中,我有一个具有bool属性的模型,不能用于数据绑定。该属性的后面是一个.NET远程处理对象,它执行一些验证并将新值写入数据库。

要求是该属性应显示为复选框,并且当用户更改该值时,新值应立即提供给.NET远程处理对象。

到目前为止我的方法: 我在我的ViewModel中创建了一个绑定到我的复选框的DependencyProperty。 在DP的propertychanged处理程序中,我正在将值写入远程处理对象的属性。

我采用这种方法遇到的问题: 如果.net远程处理对象中的验证引发异常,则吞下此异常。此外,复选框状态和数据库中的内容不同步。我试图在异常的情况下重置DP的值,但是复选框没有反映出来。 更糟糕的是,这个WPF控件被集成到现有的WinForms应用程序中。 所以我想对我在Application.ThreadException处理程序中实现的这些异常具有相同的行为。

任何想法如何处理这个? 问题是到目前为止我只听说过.NET 4.0的解决方案,但我正在使用3.5SP1。

TIA 马丁

简短演示代码:

class TestVM : DependencyObject
{
private Model _m;
public TestVM()
{
  _m = new Model();
}

public bool Value
{
  get { return (bool)GetValue(ValueProperty); }
  set { SetValue(ValueProperty, value); }
}

// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value", 
                typeof(bool), 
                typeof(TestVM), 
                new FrameworkPropertyMetadata(
                   false,
                   FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                   ((sender, e) => ((TestVM)sender).Apply(e))));

private bool _suppress = false;
private void Apply(DependencyPropertyChangedEventArgs e)
{
  if (_suppress) return;
  try
  {
    _m.Value = this.Value;
  }
  catch
  {
    _suppress = true;
    this.Value = _m.Value;
    this.OnPropertyChanged(e);
  }
  finally
  {
    _suppress = false;
  }
}

}

2 个答案:

答案 0 :(得分:0)

您不需要使用DependencyObject作为ViewModel。您只需要实现INotifyPropertyChanged以获得数据绑定支持:

class TestVM
    : INotifyPropertyChanged
{
    private Model _m;
    public TestVM()
    {
        _m = new Model();
    }

    public bool Value
    {
        get { return _m.Value; }
        set 
        {
            _m.Value = this.Value;
            OnPropertyChanged("Value");
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

请注意,如果您希望setter抛出异常,您可能希望在视图中对绑定使用ExceptionValidationRule


更新:听起来你的问题是Binding不会响应设置源的调用中的PropertyChanged事件。解决此问题的一种方法是通过在XAML中为绑定设置IsAsync=True来使用异步绑定。 WPF将在完成更新源值后处理PropertyChanged事件,并且不会认为它是可重入的调用。

您也可以通过使用转换器并通过UpdateSourceTrigger=LostFocus关闭PropertyChanged上的更新来解决这个问题,但我认为您不会想要这种行为。

答案 1 :(得分:0)

我找到了解决问题的方法。我现在正在派生我自己的绑定类来完成这项工作。

public class ExceptionBinding : Binding
{
    public ExceptionBinding(string name)
        : base(name)
    {
        Construct();
    }

    public ExceptionBinding()
        : base()
    {
        Construct();
    }

    private void Construct()
    {
        this.ValidatesOnExceptions = true;
        this.UpdateSourceExceptionFilter = new UpdateSourceExceptionFilterCallback(OnException);
    }

    private object OnException(object bindExpression, Exception exception)
    {
        // ... custom error display ...
        var exp = (BindingExpressionBase)bindExpression;
        exp.UpdateTarget();
        return null; // null needed to avoid display of the default error template
    }
}