i think i have read already all related articles but non of them help..
im trying to enable/disable a save button of datagrid
by the error state- but with no success.
this is my code:
contractor:
AddHandler(Validation.ErrorEvent, new RoutedEventHandler(OnErrorEvent));
XAML:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:local="clr-namespace:Metsuka_APP" x:Class="Metsuka_APP.MichlolimManagment"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500"
Title="MichlolimManagment"
x:Name="Michlolim_Managment" Validation.Error="Michlolim_Managment_Error">
<Page.Resources>
<DataGrid x:Name="AGAFIMDataGrid" VerticalAlignment="Center" RowEditEnding="rowEditEnding" Margin="10" FlowDirection="RightToLeft" Height="340"
AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding Source={StaticResource aGAFIMViewSource}}" Grid.Row="1"
RowDetailsVisibilityMode="VisibleWhenSelected"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
HorizontalGridLinesBrush="Silver"
VerticalGridLinesBrush="Silver">
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="agaf_nameColumn" Header="name" Width="*">
<DataGridTextColumn.Binding>
<Binding Path="agaf_name" NotifyOnValidationError="True" >
<Binding.ValidationRules>
<local:MichlolimValidationRule ValidationStep="UpdatedValue"/>
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid Margin="0,-2,0,-2"
ToolTip="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
</DataGrid>
code behind:
private int errorCount;
private void OnErrorEvent(object sender, RoutedEventArgs e)
{
var validationEventArgs = e as ValidationErrorEventArgs;
if (validationEventArgs == null)
throw new Exception("Unexpected event args");
switch (validationEventArgs.Action)
{
case ValidationErrorEventAction.Added:
{
errorCount++; break;
}
case ValidationErrorEventAction.Removed:
{
errorCount--; break;
}
default:
{
throw new Exception("Unknown action");
}
}
btnSavePop.IsEnabled = errorCount == 0;
}
but the "OnErrorEvent"
never fires- any idea why?
Try creating a class like the following:
This will provide an error whenever there is a change to the Name property. Please note that if you wish to trigger new validation checks without modifying the property you just need to call:
You will then need to change your binding to something like:
Note you will have to load your data from the DB and create a descriptor for each item you want to display in the DataGrid.
The reason behind why you aren't seeing the event being fired:
You aren't raising property change events (INotifyPropertyChanged or through a DependencyProperty) therefore the UI won't receive updates and the event won't be fired because it hasn't received an update to then perform the validation. By binding direct to your DB then you aren't raising the property change events. You can see that the Name property I suggested in my answer does raise the property changed event
You need to set
NotifyOnValidationError="True"
on your bindings - otherwise, the event won't be raised. I would recommend using theIDataErrorInfo
orINotifyDataErrorInfo
interfaces instead for an MVVM error handling approach.From my sample of your code I think you are missing specifying UpdateSourceTrigger="PropertyChanged" or UpdateSourceTrigger="LostFocus" on the DataGridTextColumn in the DataGrid instead of using the default behavior of the DataGrids binding.
That is assuming my assumptions are correct see bottom.
Your code causes OnErrorEvent to fire if i change:
To include UpdateSourceTrigger for PropertyChanged or LostFocus like so:
Assumptions - For your ValidationRule to test i made it always return false (see below). And for the test item source i am binding to a string value in 'agaf_name' property.
The attribute
in your XAML already sets a handler for the error event on the window level, however, to a method which isn't defined in your code behind fragment. Your AddHandler call looks ok, but, depending on where it is in the constructor, it might get overridden by the XAML event handler definition.
Probably not related, but you might want to change
to
in your ToolTip bindings, since the former causes binding errors if there are no errors. Unfortunately, it is still contained in the documentation samples...