绑定的价值变化直接存储在数据库中
我目前正在努力与我想添加到我的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;
}
}
}
我找到了我的问题的解决方案。我现在正在派生我自己的绑定类来完成这项工作。
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
}
}
你并不需要使用的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上的更新,但我不认为你会想要这种行为。
抱歉,但这不起作用,即使我得到异常,并在最后调用OnPropertyChanged,复选框并不反映未更新的值。 – 2010-06-24 15:01:53