Как вы решили обработать проверку данных/контроля в приложениях Silverlight?Как вы обрабатываете валидацию в Silverlight?
ответ
Не проделали большую часть этого, но лично, но хорошие стартовые точки here. Я предполагаю, что они придут как часть будущего релиза, но пока нам, вероятно, придется перевернуть наш собственный, используя валидаторы ASP.NET, в качестве отправной точки.
Вы можете исключить и исключить проверку достоверности данных.
Для управления обоих этих типов ошибок необходимо сделать 3 шага:
- Определить обработчик ошибок либо в контроле или выше в иерархии visiblity (например, контейнер, в этом случае сетка, которая содержит текстовое поле)
- Установить NotifyOnValidationError и ValidateOnException в true. Последний сообщает Binding Engine создать событие ошибки проверки при возникновении исключения. Первый сообщает Binding Engine о повышении значения BindingValidationError, когда возникает ошибка проверки.
- Создать обработчик события с именем на шаге 1.
Взято из here.
Пример кода:
// page.xaml.cs
private bool clean = true;
private void LayoutRoot_BindingValidationError(
object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
QuantityOnHand.Background = new SolidColorBrush(Colors.Red);
clean = false;
}
else if (e.Action == ValidationErrorEventAction.Removed)
{
QuantityOnHand.Background = new SolidColorBrush(Colors.White);
clean = true;
}
}
// page.xaml
<Grid x:Name="LayoutRoot" Background="White" BindingValidationError="LayoutRoot_BindingValidationError" >
<TextBox x:Name="QuantityOnHand"
Text="{Binding Mode=TwoWay, Path=QuantityOnHand,
NotifyOnValidationError=true, ValidatesOnExceptions=true }"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Height="30" Width="90"red
Grid.Row="4" Grid.Column="1" />
// book.cs
public int QuantityOnHand
{
get { return quantityOnHand; }
set
{
if (value < 0)
{
throw new Exception("Quantity on hand cannot be negative!");
}
quantityOnHand = value;
NotifyPropertyChanged("QuantityOnHand");
} // end set
}
Вы можете посмотреть на PostSharp, что делает приписывание ваша модель данных на стороне клиента очень просто.
Если вы предоставите пример использования PostSharp для подтверждения валидации, я удалю нижний предел. – 2010-01-04 16:23:43
Если у вас возникли проблемы с попыткой реализовать это, дело не в том, что ваш код сломан, это потому, что функция разбита в DataGrid. Посмотрите статью Джесси Либерти here.
Правильная ссылка: http://jesseliberty.com/2008/10/22/it-aint-you-babe%E2%80%A6-a-not-a-bug-bug-in-datagrid/ – 2010-05-07 20:25:37
Очень простой источник управления проверки кода дается в этом месте:
http://silverlightvalidator.codeplex.com/SourceControl/changeset/view/20754#
Ниже приведены условия, при которых она работает. 1. Индикатор, показывающий недопустимые значения, принимает положение элемента управления для проверки, поэтому элементы управления должны быть плотно упакованы в строку и столбец так, чтобы они указывали рядом с элементом управления. 2. Он не работает для проверки в ChildWindow.
мне пришлось изменить код, чтобы включить условия childwindow в классе validatorbase следующим образом:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Silverlight.Validators.Controls;
namespace Silverlight.Validators
{
public enum ValidationType
{
Validator,
OnDemand
}
public abstract class ValidatorBase : DependencyObject
{
protected ValidatorManager Manager { get; set; }
public string ManagerName { get; set; }
public ValidationType ValidationType { get; set; }
public IIndicator Indicator { get; set; }
public FrameworkElement ElementToValidate { get; set; }
public bool IsRequired { get; set; }
public bool IsValid { get; set; }
public Brush InvalidBackground { get; set; }
public Brush InvalidBorder { get; set; }
public Thickness InvalidBorderThickness { get; set; }
public string ErrorMessage { get; set; }
private Brush OrigBackground = null;
private Brush OrigBorder = null;
private Thickness OrigBorderThickness = new Thickness(1);
private object OrigTooltip = null;
public ValidatorBase()
{
IsRequired = false;
IsValid = true;
ManagerName = "";
this.ValidationType = ValidationType.Validator;
}
public void Initialize(FrameworkElement element)
{
ElementToValidate = element;
element.Loaded += new RoutedEventHandler(element_Loaded);
}
private bool loaded = false;
public UserControl UserControl { get; set; }
public ChildWindow ChildUserControl { get; set; }
private void element_Loaded(object sender, RoutedEventArgs e)
{
if (!loaded)
{
this.UserControl = FindUserControl(ElementToValidate);
//UserControl o = FindUserControl(ElementToValidate);
this.ChildUserControl = FindChildUserControl(ElementToValidate);
//MessageBox.Show(o.GetType().BaseType.ToString());
//no usercontrol. throw error?
if ((this.UserControl == null) && (this.ChildUserControl==null)) return;
if (this.UserControl != null)
this.Manager = FindManager(this.UserControl, ManagerName);
else if (this.ChildUserControl != null)
this.Manager = FindManager(this.ChildUserControl, ManagerName);
if (this.Manager == null)
{
System.Diagnostics.Debug.WriteLine(String.Format("No ValidatorManager found named '{0}'", ManagerName));
throw new Exception(String.Format("No ValidatorManager found named '{0}'", ManagerName));
}
this.Manager.Register(ElementToValidate, this);
if (ValidationType == ValidationType.Validator)
{
ActivateValidationRoutine();
}
//Use the properties from the manager if they are not set at the control level
if (this.InvalidBackground == null)
{
this.InvalidBackground = this.Manager.InvalidBackground;
}
if (this.InvalidBorder == null)
{
this.InvalidBorder = this.Manager.InvalidBorder;
if (InvalidBorderThickness.Bottom == 0)
{
this.InvalidBorderThickness = this.Manager.InvalidBorderThickness;
}
}
if (this.Indicator ==null)
{
Type x = this.Manager.Indicator.GetType();
this.Indicator = x.GetConstructor(System.Type.EmptyTypes).Invoke(null) as IIndicator;
foreach (var param in x.GetProperties())
{
var val = param.GetValue(this.Manager.Indicator, null);
if (param.CanWrite && val!= null && val.GetType().IsPrimitive)
{
param.SetValue(this.Indicator, val, null);
}
}
}
loaded = true;
}
ElementToValidate.Loaded -= new RoutedEventHandler(element_Loaded);
}
public void SetManagerAndControl(ValidatorManager manager, FrameworkElement element)
{
this.Manager = manager;
this.ElementToValidate = element;
}
public bool Validate(bool checkControl)
{
bool newIsValid;
if (checkControl)
{
newIsValid= ValidateControl() && ValidateRequired();
}
else
{
newIsValid = ValidateRequired();
}
if (newIsValid && !IsValid)
{
ControlValid();
}
if (!newIsValid && IsValid)
{
ControlNotValid();
}
IsValid=newIsValid;
return IsValid;
}
public virtual void ActivateValidationRoutine()
{
ElementToValidate.LostFocus += new RoutedEventHandler(ElementToValidate_LostFocus);
ElementToValidate.KeyUp += new KeyEventHandler(ElementToValidate_KeyUp);
}
/// <summary>
/// Find the nearest UserControl up the control tree for the FrameworkElement passed in
/// </summary>
/// <param name="element">Control to validate</param>
protected static UserControl FindUserControl(FrameworkElement element)
{
if (element == null)
{
return null;
}
if (element.Parent != null)
{
//MessageBox.Show(element.Parent.GetType().BaseType.ToString());
if (element.Parent is UserControl)
{
return element.Parent as UserControl;
}
return FindUserControl(element.Parent as FrameworkElement);
}
return null;
}
protected static ChildWindow FindChildUserControl(FrameworkElement element)
{
if (element == null)
{
return null;
}
if (element.Parent != null)
{
//MessageBox.Show(element.Parent.GetType().BaseType.ToString());
if (element.Parent is ChildWindow)
{
return element.Parent as ChildWindow;
}
return FindChildUserControl(element.Parent as FrameworkElement);
}
return null;
}
protected virtual void ElementToValidate_KeyUp(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(delegate() { Validate(false); });
}
protected virtual void ElementToValidate_LostFocus(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(delegate() { Validate(true); });
}
protected abstract bool ValidateControl();
protected bool ValidateRequired()
{
if (IsRequired && ElementToValidate is TextBox)
{
TextBox box = ElementToValidate as TextBox;
return !String.IsNullOrEmpty(box.Text);
}
return true;
}
protected void ControlNotValid()
{
GoToInvalidStyle();
}
protected void ControlValid()
{
GoToValidStyle();
}
protected virtual void GoToInvalidStyle()
{
if (!string.IsNullOrEmpty(this.ErrorMessage))
{
object tooltip = ToolTipService.GetToolTip(ElementToValidate);
if (tooltip != null)
{
OrigTooltip = tooltip;
}
//causing a onownermouseleave error currently...
this.ElementToValidate.ClearValue(ToolTipService.ToolTipProperty);
SetToolTip(this.ElementToValidate, this.ErrorMessage);
}
if (Indicator != null)
{
Indicator.ShowIndicator(this);
}
if (ElementToValidate is TextBox)
{
TextBox box = ElementToValidate as TextBox;
if (InvalidBackground != null)
{
if (OrigBackground == null)
{
OrigBackground = box.Background;
}
box.Background = InvalidBackground;
}
if (InvalidBorder != null)
{
if (OrigBorder == null)
{
OrigBorder = box.BorderBrush;
OrigBorderThickness = box.BorderThickness;
}
box.BorderBrush = InvalidBorder;
if (InvalidBorderThickness != null)
{
box.BorderThickness = InvalidBorderThickness;
}
}
}
}
protected virtual void GoToValidStyle()
{
if (!string.IsNullOrEmpty(this.ErrorMessage))
{
this.ElementToValidate.ClearValue(ToolTipService.ToolTipProperty);
if (this.OrigTooltip != null)
{
SetToolTip(this.ElementToValidate, this.OrigTooltip);
}
}
if (Indicator != null)
{
Indicator.HideIndicator();
}
if (ElementToValidate is TextBox)
{
TextBox box = ElementToValidate as TextBox;
if (OrigBackground != null)
{
box.Background = OrigBackground;
}
if (OrigBorder != null)
{
box.BorderBrush = OrigBorder;
if (OrigBorderThickness != null)
{
box.BorderThickness = OrigBorderThickness;
}
}
}
}
protected void SetToolTip(FrameworkElement element, object tooltip)
{
Dispatcher.BeginInvoke(() =>
ToolTipService.SetToolTip(element, tooltip));
}
private ValidatorManager FindManager(UserControl c, string groupName)
{
string defaultName = "_DefaultValidatorManager";
var mgr = this.UserControl.FindName(ManagerName);
if (mgr == null)
{
mgr = this.UserControl.FindName(defaultName);
}
if (mgr == null)
{
mgr = new ValidatorManager()
{
Name = defaultName
};
Panel g = c.FindName("LayoutRoot") as Panel;
g.Children.Add(mgr as ValidatorManager);
}
return mgr as ValidatorManager;
}
private ValidatorManager FindManager(ChildWindow c, string groupName)
{
string defaultName = "_DefaultValidatorManager";
var mgr = this.ChildUserControl.FindName(ManagerName);
if (mgr == null)
{
mgr = this.ChildUserControl.FindName(defaultName);
}
if (mgr == null)
{
mgr = new ValidatorManager()
{
Name = defaultName
};
Panel g = c.FindName("LayoutRoot") as Panel;
g.Children.Add(mgr as ValidatorManager);
}
return mgr as ValidatorManager;
}
}
}
я ожидал увидеть, какой контроль над вызвал исключение в ValidationErrorEventArgs (http://msdn.microsoft .com/EN-US/библиотека/system.windows.controls.validationerroreventargs.aspx). Поэтому я переместил событие BindingValidationError из Grid и в текстовые поля, которые могут вызвать исключение. Таким образом, я могу проверить, какой элемент управления вызвал исключение в параметре отправителя. – russau 2009-07-01 04:16:36