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}" />
我的附加屬性自動應用驗證,在窗口中的每個綁定,所以個人文本框不必擔心ABO ut驗證。
要做到這一點,我用這個一般techinique:
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;
}
}
查看驗證類的MSDN文檔中如何創建errorTemplate資源的例子。還要注意的是:
- 我ValidationHelper類不阻止您在 個別文本框設置自定義Validation.ErrorTemplate值。這些將覆蓋ValidationHelper.ErrorTemplate。
- 您可以輕鬆地添加比文本框其他控件和非文本
你就是唯一一個誰知道如何醜陋,當一行代碼強制關進9行代碼的其他屬性的支持。 – nyconing 2017-10-31 07:09:31