我正在努力解决我正在尝试添加到我的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;
}
}
}
答案 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
}
}