I have a DataGrid on my page and the collection object that is bound to it has some validation on it.
I was wandering if there is a way to fire validation on the grid when say Save button is clicked. Meaning right before I push my data to database, I want to fire validation on grid to make sure that the grid or collection objects bound to it are in valid
state. If not, display a message to use and ask user to correct it.
You can create a validate method on your business entity as in the snippet below and then itterate through your collection and validate each item. If you implemented the IEditableObject interface on your business object you can also extend that to mark a
property as updated in order for you to use Linq to only return your dirty records, this way you can validate a smaller set.
/// <summary>
/// Validate this Object by calling the Validator
/// </summary>
/// <typeparam name="T"></typeparam>public virtual void Validate()
{
var validationContext = new ValidationContext(this, null, null);
Validator.ValidateObject(this, validationContext);
}
#endregion Methods
Thank esite you for your quick answer. Could you please expand on this little.
"If you implemented the IEditableObject interface on your business object you can also extend that to mark a property as updated in order for you to use Linq to only return your dirty records, this way you can validate a smaller set."
It would be nice if all invalid items would popup with error state (red) in the grid. Also, after iterating through the collection and calling validate() method on each object, would you be able to inquire and say is there any invalid object in collection.
If so, display some error message to user and do not continue.
That is a very good article. However, the solution in the article only validates.
- Once we modify the content of a particular cell (cell validation)
- Once we modify the content of a particular datagrid row (would like to commit changes to row) (Row Validation). In this blog, I will try to give an intro both cell validation and row validation by using examples.
What I need is when user clicks a Submit button to save data, I want to make sure all data in DataGrid is valid. If not high light the cell with red error state. And 1) I am wandering if this is possible. 2) Validator.ValidateObject only validates the
validator attributes(Required, Range, etc...) on property. But does not do anything, if I have validtion like below.
By the way my DataGrid will be initially be loaded with some invalid data becuase thats how it exist in database plus an addition of new column this release that will be zero to begin with. And so initially setter validation is turned off by a global flag(Global.IsValidate).
public new decimal RefurbPrice
{
get
{
return refurbPrice;
}
set
{
if (Global.IsValidate && (value < NewCost || value < 0))
{
throw new ValidationException("Refurb Price can not be greater then New Cost or Negative.");
}
refurbPrice = value;
RaisePropertyChanged("RefurbPrice");
}
}
Unfortunately this is exactly where the Silverlight validation breaks down, something needs to change in order for the Validator to check the validation on the Setter of the property. Now on the BindingExpression exists a method called UpdateSource which
forces validation on a control, in fact you can set in your binding to only check validation when you call this method by setting UpdateSourceTrigger=Explicit.
I have been playing with this for a little while now, trying to get my facts right and I believe I am still not 100% there but this is what I have thus far:
I created a BaseEntity class that contains a IsValid property and all my Entities inherits from this BaseEntity. I want to use IsValid to be able to later check if that Entity was in fact valid to be saved.
public static class DependencyObjectExtension
{
public static List GetChildObjects(this DependencyObject obj, string name)
{
var retVal = new List();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
object c = VisualTreeHelper.GetChild(obj, i);
if (c.GetType().FullName == typeof(T).FullName && (String.IsNullOrEmpty(name) || ((FrameworkElement)c).Name == name))
{
retVal.Add((T)c);
}
var gc = ((DependencyObject)c).GetChildObjects(name);
if (gc != null)
retVal.AddRange(gc);
}
return retVal;
}
public static T GetChildObject(this DependencyObject obj, string name) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
object c = VisualTreeHelper.GetChild(obj, i);
if (c.GetType().FullName == typeof(T).FullName && (String.IsNullOrEmpty(name) || ((FrameworkElement)c).Name == name))
{
return (T)c;
}
object gc = ((DependencyObject)c).GetChildObject(name);
if (gc != null)
return (T)gc;
}
return null;
}
}
You will need to create a class and copy the above in it, make sure your namespaces match, as this cool piece of code is an extender and extends the DependencyObject.
In another Helper class I have a piece of code that uses the extension above to get controls on my page and then call the UpdateSource on each individually. My code look like this, but you will need to extend it for your purposes:
public virtual void ValidateCollection(IEnumerable collection, DependencyObject dependencyObject)
{
//Reset the IsValid property before validationforeach (T entity in collection)
{
(entity as BaseEntity).IsValid = true;
}
//TextBoxes
var textBoxes = dependencyObject.GetChildObjects(null);
foreach (var control in textBoxes)
UpdateSource(control, TextBox.TextProperty);
//ComboBoxes
var comboBoxes = dependencyObject.GetChildObjects(null);
foreach (var control in comboBoxes)
UpdateSource(control, ComboBoxEdit.EditValueProperty);
}
private void UpdateSource(FrameworkElement control, DependencyProperty dp)
{
var binding = control.GetBindingExpression(dp);
if (binding != null)
binding.UpdateSource();
}
From the example above you will see that I only cater for TextBoxes and ComboBoxEdit (devexpress).
This is where you will need to jump in as I haven't done a Grid yet but I believe that might be able to pass a Grid.RowProperty here.
The code I then call on my save looks like this:
/// <summary>
/// Save a Issue
/// </summary>
/// <param name="taskEntity"></param>public void Save(IProgress progressControl, FrameworkElement targetControl)
{
if (_IssueService != null)
{
try
{
List dirtyCollection = GetDirtyRecords(Model).ToList();
//First Pass Validation
ValidateCollection(dirtyCollection, targetControl);
foreach (IssueEntity entity in dirtyCollection)
{
if (!((BaseEntity)entity).IsValid)
return;
}
//Second Pass Validation
ValidateCollection(dirtyCollection);
//Save Object
progressControl.StartSave(targetControl);
_IssueService.SaveIssue(dirtyCollection);
}
catch (ValidationException ex)
{
ShowValidationMessage(ex.Message);
}
}
}
On your XAML page you will need to also register the BindingValidationError for LayoutRoot to do something like this:
private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.OriginalSource is FrameworkElement)
{
object dataContext = ((FrameworkElement)e.OriginalSource).DataContext;
if (dataContext is BaseEntity)
((BaseEntity)dataContext).IsValid = false;
}
}
It is still a bit ugly, trying to clean it up, but at least now when I click on Save, my validation errors are showing.
You can also add a ValidationSummary control on your page that will show up when a Binding Error occured.
spatemp
Member
8 Points
58 Posts
DataGrid Validation when Save button is clicked
Nov 19, 2009 09:22 PM | LINK
I have a DataGrid on my page and the collection object that is bound to it has some validation on it.
I was wandering if there is a way to fire validation on the grid when say Save button is clicked. Meaning right before I push my data to database, I want to fire validation on grid to make sure that the grid or collection objects bound to it are in valid state. If not, display a message to use and ask user to correct it.
Thanks.
esite
Contributor
3301 Points
700 Posts
Re: DataGrid Validation when Save button is clicked
Nov 20, 2009 01:56 AM | LINK
You can create a validate method on your business entity as in the snippet below and then itterate through your collection and validate each item. If you implemented the IEditableObject interface on your business object you can also extend that to mark a property as updated in order for you to use Linq to only return your dirty records, this way you can validate a smaller set.
spatemp
Member
8 Points
58 Posts
Re: DataGrid Validation when Save button is clicked
Nov 20, 2009 11:29 AM | LINK
Thank esite you for your quick answer. Could you please expand on this little.
"If you implemented the IEditableObject interface on your business object you can also extend that to mark a property as updated in order for you to use Linq to only return your dirty records, this way you can validate a smaller set."
It would be nice if all invalid items would popup with error state (red) in the grid. Also, after iterating through the collection and calling validate() method on each object, would you be able to inquire and say is there any invalid object in collection. If so, display some error message to user and do not continue.
Thanks again.
Min-Hong Tan...
All-Star
28750 Points
3295 Posts
Re: DataGrid Validation when Save button is clicked
Nov 23, 2009 08:03 AM | LINK
Hi,
Silverlight technology's validation system is very powerful.
This is a very nice article, detailed and neat.
http://blogs.msdn.com/nagasatish/archive/2009/03/22/datagrid-validation.aspx
Best Regards
Microsoft Online Community Support
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
spatemp
Member
8 Points
58 Posts
Re: DataGrid Validation when Save button is clicked
Nov 23, 2009 11:16 AM | LINK
MinHong,
That is a very good article. However, the solution in the article only validates.
- Once we modify the content of a particular cell (cell validation)
- Once we modify the content of a particular datagrid row (would like to commit changes to row) (Row Validation). In this blog, I will try to give an intro both cell validation and row validation by using examples.
What I need is when user clicks a Submit button to save data, I want to make sure all data in DataGrid is valid. If not high light the cell with red error state. And 1) I am wandering if this is possible. 2) Validator.ValidateObject only validates the validator attributes(Required, Range, etc...) on property. But does not do anything, if I have validtion like below.
By the way my DataGrid will be initially be loaded with some invalid data becuase thats how it exist in database plus an addition of new column this release that will be zero to begin with. And so initially setter validation is turned off by a global flag(Global.IsValidate).
NewCost is a property on this object as well.
esite
Contributor
3301 Points
700 Posts
Re: DataGrid Validation when Save button is clicked
Nov 23, 2009 01:30 PM | LINK
Apologies for the late response.
Unfortunately this is exactly where the Silverlight validation breaks down, something needs to change in order for the Validator to check the validation on the Setter of the property. Now on the BindingExpression exists a method called UpdateSource which forces validation on a control, in fact you can set in your binding to only check validation when you call this method by setting UpdateSourceTrigger=Explicit.
I have been playing with this for a little while now, trying to get my facts right and I believe I am still not 100% there but this is what I have thus far:
I created a BaseEntity class that contains a IsValid property and all my Entities inherits from this BaseEntity. I want to use IsValid to be able to later check if that Entity was in fact valid to be saved.
Then I basically copied this class from another post http://forums.silverlight.net/forums/t/140537.aspx
You will need to create a class and copy the above in it, make sure your namespaces match, as this cool piece of code is an extender and extends the DependencyObject.
In another Helper class I have a piece of code that uses the extension above to get controls on my page and then call the UpdateSource on each individually. My code look like this, but you will need to extend it for your purposes:
From the example above you will see that I only cater for TextBoxes and ComboBoxEdit (devexpress).
This is where you will need to jump in as I haven't done a Grid yet but I believe that might be able to pass a Grid.RowProperty here.
The code I then call on my save looks like this:
On your XAML page you will need to also register the BindingValidationError for LayoutRoot to do something like this:
It is still a bit ugly, trying to clean it up, but at least now when I click on Save, my validation errors are showing.
You can also add a ValidationSummary control on your page that will show up when a Binding Error occured.
HTH
teyc
Contributor
2427 Points
615 Posts
Re: DataGrid Validation when Save button is clicked
Jul 14, 2010 03:34 AM | LINK
Here's a possibly simpler method. You can loop through your entities and check them.
Validate each entity: ValidationContext context = new ValidationContext(person, null, null); Validator.TryValidateObject( person, context, person.ValidationErrors);Alternately, you can try the technique here:
http://devjitsu.com/blog/2010/06/03/entity-level-validation-with-ria-services
(Mark as answered if this is what you're trying to achieve)