2010-06-24 58 views
0

我目前正在努力与我想添加到我的WPF项目的绑定之一。 在应用程序中,我有一个不能用于数据绑定的bool属性的模型。该属性后面是一个.NET Remoting对象,它执行一些验证并将新值写入数据库。绑定的价值变化直接存储在数据库中

需要确保属性应显示为复选框,并且随着用户更改值,新值应立即提供给.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; 
    } 
} 

}

回答

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

你并不需要使用的DependencyObject为您的视图模型。你只需要执行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


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

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

+0

抱歉,但这不起作用,即使我得到异常,并在最后调用OnPropertyChanged,复选框并不反映未更新的值。 – 2010-06-24 15:01:53