简体   繁体   English

WPF-验证错误事件不会触发

[英]WPF- validation error event doesn't fire

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. 我试图通过错误状态启用/禁用datagrid的保存按钮 - 但没有成功。

this is my code: 这是我的代码:

contractor: 承包商:

AddHandler(Validation.ErrorEvent, new RoutedEventHandler(OnErrorEvent));

XAML: 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? 但是"OnErrorEvent"永远不会触发 - 任何想法为什么?

Try creating a class like the following: 尝试创建如下所示的类:

public class AgafDescriptor : INotifyPropertyChanged, IDataErrorInfo
{
    private string _name;

    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name = value;

                RaisePropertyChanged(x => x.Name);
            }
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged<T>(Expression<Func<AgafDescriptor, T>> propertyExpression)
    {
        PropertyChangedEventHandler localPropertyChanged = this.PropertyChanged as PropertyChangedEventHandler;

        if ((localPropertyChanged != null) && (propertyExpression != null))
        {
            MemberExpression body = propertyExpression.Body as MemberExpression;

            if (body != null)
            {
                localPropertyChanged(this, new PropertyChangedEventArgs(body.Member.Name));
            }
        }
    }

    #endregion

    #region IDataErrorInfo Members

    // Does nothing in WPF.
    public string Error
    {
        get { return null; }
    }

    public string this[string columnName]
    {
        get
        {
            string returnVal = null;

            if (string.Equals("Name", columnName, StringComparison.Ordinal))
            {
                if (string.IsNullOrWhiteSpace(Name))
                {
                    returnVal = "A name must be supplied.";
                }
            }

            return returnVal;
        }
    }

    #endregion
}

This will provide an error whenever there is a change to the Name property. 只要Name属性发生更改,这将提供错误。 Please note that if you wish to trigger new validation checks without modifying the property you just need to call: 请注意,如果您希望在不修改属性的情况下触发新的验证检查,则只需调用:

  RaisePropertyChanged(x => x.Name);

You will then need to change your binding to something like: 然后,您需要将绑定更改为:

<DataGridTextColumn x:Name="agaf_nameColumn"  Header="name" Width="*" Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, NotifyOnValidationError=True}"/>

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. 请注意,您必须从数据库加载数据,并为要在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. 您没有提出属性更改事件(INotifyPropertyChanged或通过DependencyProperty),因此UI将不会接收更新,并且不会触发事件,因为它尚未收到更新然后执行验证。 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 您可以看到我在答案中建议的Name属性确实引发了属性更改事件

You need to set NotifyOnValidationError="True" on your bindings - otherwise, the event won't be raised. 您需要在绑定上设置NotifyOnValidationError="True" - 否则,不会引发该事件。 I would recommend using the IDataErrorInfo or INotifyDataErrorInfo interfaces instead for an MVVM error handling approach. 我建议使用IDataErrorInfoINotifyDataErrorInfo接口来代替MVVM错误处理方法。

The attribute 属性

Validation.Error="Michlolim_Managment_Error"

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. 在您的XAML中,已经在窗口级别为错误事件设置了一个处理程序,而不是在代码隐藏片段中定义的方法。 Your AddHandler call looks ok, but, depending on where it is in the constructor, it might get overridden by the XAML event handler definition. 您的AddHandler调用看起来没问题,但是,根据它在构造函数中的位置,它可能会被XAML事件处理程序定义覆盖。

Probably not related, but you might want to change 可能没有相关性,但您可能想要改变

(Validation.Errors)[0].ErrorContent

to

(Validation.Errors)/ErrorContent

in your ToolTip bindings, since the former causes binding errors if there are no errors. 在您的ToolTip绑定中,因为如果没有错误,前者会导致绑定错误。 Unfortunately, it is still contained in the documentation samples... 不幸的是,它仍然包含在文档样本中......

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. 从我的代码示例中,我认为您缺少在DataGrid中的DataGridTextColumn上指定UpdateSourceTrigger =“PropertyChanged”或UpdateSourceTrigger =“LostFocus”,而不是使用DataGrids绑定的默认行为。

That is assuming my assumptions are correct see bottom. 假设我的假设是正确的,请参见底部。

Your code causes OnErrorEvent to fire if i change: 如果我更改,您的代码会导致OnErrorEvent触发:

<DataGridTextColumn.Binding>
  <Binding Path="agaf_name" NotifyOnValidationError="True"  >
  ...

To include UpdateSourceTrigger for PropertyChanged or LostFocus like so: 要包含PropertyChanged或LostFocus的UpdateSourceTrigger,如下所示:

<DataGridTextColumn.Binding>
   <Binding Path="agaf_name" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" >
   ....

在此输入图像描述

Assumptions - For your ValidationRule to test i made it always return false (see below). 假设 - 对于你的ValidationRule进行测试,我总是返回false(见下文)。 And for the test item source i am binding to a string value in 'agaf_name' property. 对于测试项目源,我绑定到'agaf_name'属性中的字符串值。

public class MichlolimValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        return new ValidationResult(false, "bad");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM