在我的模型中,我有很多不同对象的属性,我在设置对象的值时检查值,如果值不被接受,我将抛出一个异常,这对Windows窗体的属性很好,但现在我'我试图使用WPF设计一个新的界面。 在WPF中,当我将属性绑定到像文本框这样的控件时,当值更改时,我不知道如何处理异常并显示错误消息。 例如:
public string ConnectionString
{
get
{
return (_ConnectionString);
}
set
{
try
{
_ConnectionString = value ;
_SqlConnection = new System.Data.SqlClient.SqlConnection(_ConnectionString);
_ConnectionTested = true;
}
catch (Exception caught)
{
_ConnectionTested = false;
_TableNameTested = false;
_FieldNameTested = false;
_ConditionTested = false;
_ConnectionString = "";
//----delete values----
ValuesCollection.Clear();
throw (new Exception("Can not Open the connection String \nReason : " + caught.Message ));
}
}
}
和wpf部分类似:
<TextBox TextWrapping="Wrap" x:Name="ConnectionStringTextBox" Text="{Binding Path=ConnectionString, Mode=TwoWay}"/>
无论如何,当文本框中的值被更改时,是否存在检查模型是否抛出异常,然后向用户显示exception.message?
感谢
答案 0 :(得分:5)
Kent使用ValidationRule和ExceptionValidationRule是完全正确的。但是,你会发现这个解决方案非常不愉快,因为你有很多绑定到这样的字段的情况。在许多地方,你将取代这样的东西:
<TextBox Text="{Binding Value}" />
用这个:
<TextBox Validation.ErrorTemplate="{StaticResource errorTemplate}">
<TextBox.Text>
<Binding Path="Value">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
因为这是如此笨拙,我喜欢创建一个自动应用验证规则的继承附加属性,所以我要说的是:
<Window
ValidationHelper.ErrorTemplate="{StaticResource errorTemplate}"
...
<TextBox Text="{Binding Value}" />
<TextBox Text="{Binding OtherValue}" />
我的附属属性会自动对窗口中的每个绑定应用验证,因此各个文本框不必担心验证。
要做到这一点,我使用这个一般技术:
public class ValidationHelper : DependencyObject
{
[ThreadStatic]
static List<DependencyObject> _objectsNeedingValidationUpdate;
public static ControlTemplate GetErrorTemplate(DependencyObject obj) { return (ControlTemplate)obj.GetValue(ErrorTemplateProperty); }
public static void SetErrorTemplate(DependencyObject obj, ControlTemplate value) { obj.SetValue(ErrorTemplateProperty, value); }
public static readonly DependencyProperty ErrorTemplateProperty = DependencyProperty.RegisterAttached("ErrorTemplate", typeof(ControlTemplate), typeof(ValidationHelper), new FrameworkPropertyMetadata
{
Inherits = true,
PropertyChangedCallback = (obj, e) =>
{
if(e.NewValue)
if(_objectsNeedingValidationUpdate!=null)
_objectsNeedingValidationUpdate.Add(obj);
else
{
_objectsNeedingValidationUpdate = new List<DependencyObject>();
_objectsNeedingValidationUpdate.Add(obj);
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new Action(UpdateValidations));
}
},
});
static void UpdateValidations()
{
List<DependencyObject> objects = _objectsNeedingValidationUpdate;
_objectsNeedingValidationUpdate = null;
if(objects!=null)
foreach(DependencyObject obj in objects)
UpdateValidations(obj);
}
static void UpdateValidations(DependencyObject obj)
{
// My regular code uses obj.GetLocalValueEnumerator here, but that would require some other complexity
if(UpdateValidations(obj, TextBox.TextProperty))
if(Validation.GetErrorTemplate(obj)==null)
Validation.SetErrorTemplate(obj, ValidationHelper.GetErrorTemplate(obj));
}
static bool UpdateValidations(DependencyObject obj, DependencyProperty prop)
{
var binding = BindingOperations.GetBinding(obj, prop);
if(binding!=null &&
binding.Mode==BindingMode.TwoWay &&
!binding.ValidationRules.Any(rule => rule is ExceptionValidationRule))
{
binding.ValidationRules.Add(new ExceptionValidationRule());
BindingOperations.SetBinding(obj, prop, binding); // Required to get new rule to work
return true;
}
return false;
}
}
有关如何创建errorTemplate资源的示例,请参阅Validation类的MSDN文档。另请注意:
答案 1 :(得分:3)
看看binding validation。 Binding
类有一个ValidationRules
集合,您可以在其中添加ExceptionValidationRule
。