2015-05-13 23 views
9

我想我已經讀過所有相關文章,但他們不幫助..WPF-驗證錯誤不會觸發事件

我嘗試使由錯誤國有但是隨着/禁用datagrid保存按鈕沒有成功。

這是我的代碼:

承包商:

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> 

後面的代碼:

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; 
    } 

"OnErrorEvent"從未fires-任何想法w^HY?

+0

您可以發佈您在DataGrid中顯示的模型的代碼嗎?主要是agaf_name屬性。 – Bijington

+0

其基於數據庫 - 你想看到什麼樣的代碼? – DasDas

+0

我想看看如何定義屬性來查看綁定的工作方式。正如Adi剛剛在回答中所建議的那樣,您需要實現IDataErrorInfo,但是您還需要綁定到依賴項屬性或對正在綁定的類使用INotifyPropertyChanged – Bijington

回答

2

屬性

Validation.Error="Michlolim_Managment_Error" 

在XAML中已經設置了一個處理程序,在窗口級別的錯誤事件,然而,一個沒有在你的代碼片段後面定義的方法。您的AddHandler調用看起來不錯,但根據它在構造函數中的位置,它可能會被XAML事件處理程序定義覆蓋。

也許沒有關係,但你可能要改變

(Validation.Errors)[0].ErrorContent 

(Validation.Errors)/ErrorContent 

在你的工具提示綁定,因爲前者的原因綁定錯誤,如果沒有錯誤。不幸的是,它仍然包含在文檔樣本中...

2

您需要在綁定上設置NotifyOnValidationError="True" - 否則不會引發該事件。我建議使用IDataErrorInfoINotifyDataErrorInfo接口來代替MVVM錯誤處理方法。

+0

我已經在我的代碼中包含該行了!順便說一句,即時通訊不使用MVVM – DasDas

3

嘗試創建一個類如下所示:

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 
} 

每當有一個變化的名稱屬性這將提供一個錯誤。請注意,如果您希望觸發新的驗證檢查,而無需修改屬性,你只需要調用:

RaisePropertyChanged(x => x.Name); 

那麼你需要改變你的結合是這樣的:

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

注意,您必須從數據庫加載數據併爲要在DataGrid中顯示的每個項目創建一個描述符。

背後爲什麼你沒有看到該事件的原因被解僱:

您還沒有提高的屬性更改事件(INotifyPropertyChanged的或通過一個DependencyProperty)因此UI將不會收到更新和事件將不會被解僱,因爲它沒有收到更新,然後執行驗證。通過直接綁定到你的數據庫,那麼你不會提高財產變更事件。你可以看到,我在答覆建議的名稱屬性不會提升屬性更改事件

+0

和虐待必須創建這樣一個類,我需要檢查每一列? – DasDas

+0

不,你應該爲每一列你想檢查1財產。 – Bijington

+0

但仍然,這並沒有回答我的問題爲什麼事件沒有被解僱:( – DasDas

1

從我的代碼示例中,我認爲您缺少在DataGrid的DataGridTextColumn中指定UpdateSourceTrigger =「PropertyChanged」或UpdateSourceTrigger =「LostFocus」,而不是使用DataGrids綁定的默認行爲。

這是假設我的假設是正確的,請參閱底部。

你的代碼會導致OnErrorEvent火,如果我改變:

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

要包括UpdateSourceTrigger爲的PropertyChanged或引發LostFocus像這樣:

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

enter image description here

假設 - 爲了您的有效性規則來測試我讓它總是返回false(見下文)。對於測試項目源,我綁定到'agaf_name'屬性中的字符串值。

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