I want to achieve a pretty simple task, but none of the solutions here on SO or otherwise found have helped me so far:
I have a WPF DataGrid
, which is b
Why dont you catch the attached bubbling routed event Validation.Error
on your data grid?
<DataGrid x:Name="mydataGrid" Validation.Error="MyValidationErrorHandler" ... />
Make sure you have NotifyOnValidationError=true
in your bindings. This way you would know that error has been raised and show that in your messagebox.
But do you really "know" there are errors on the datagrid? I mean do you see the errors highlighted using red border , tooltips, row validation error template etc? Isnt that sufficient to indicate to user?
Cant you use
Validation.GetHasError(mydataGrid)
to check if its in error?
This seems a near duplicate of this [question]: (Checking If Any WPF DataGrid Cell Has Error).
Here's an answer that's more XAMly. It relies on the fact that when an error template is shown its IsVisible property toggles.
Just create a ValidationErrorTemplate for the DataGridRow [1]: (http://msdn.microsoft.com/en-us/library/ee622975.aspx)
Create 2 attacheded properties. The value of the one attached property is the DataGrid itself,
local:DataGridValidator.DataGridToMarkForValidationErrors="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}"
Attach the property to the root control of the ValidationErrorTemplate.
In the callback for the attached property set the 2nd property on the DataGrid to show whether it has errors:
private static void DataGridPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var fe = dependencyObject as FrameworkElement;
var target = args.NewValue as DependencyObject;
if (fe != null && target != null)
{
target.SetValue(IsFreeOfValidatoionErrorsProperty, !fe.IsVisible);
fe.IsVisibleChanged += (_1, _) =>
{
target.SetValue(IsFreeOfValidatoionErrorsProperty, !fe.IsVisible);
};
}
Now the DataGrid has a property (IsFreeOfValidatoionErrorsProperty) showing whether it has errors or not. I made the property default positive so I could easily AND it with my VM IsDirty/CanSave property.
OK, I've worked it out. The following does what I want:
public static DataGridRow GetRow(DataGrid grid, int index)
{
DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
if (row == null)
{
// May be virtualized, bring into view and try again.
grid.UpdateLayout();
grid.ScrollIntoView(grid.Items[index]);
row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
In the code for my "OK" button I do:
for (int i = 0; i < dgvData.Items.Count; i++)
{
DataGridRow row = GetRow(dgvData, i);
if (row != null && Validation.GetHasError(row))
{
hasDataGridErrors = true;
break;
}
}