2017-02-27 4 views
1

Stellen Sie sich ein DataGrid vor, dessen ItemsSource auf ObservableCollection festgelegt ist. Diese Sammlung bietet ein Ansichtsmodell für jede Zeile in der DataGrid. Das Ansichtsmodell wiederum liefert die Daten, die in einer Zeile angezeigt werden, und einen Befehl, der diese Daten ändern kann. Außerdem fügte ich der RowValidationRules-Eigenschaft von DataGrid eine Regel hinzu. Diese Validierungsregel funktioniert einwandfrei, wenn ich ungültige Daten eingabe.Überprüfen Sie die Zeile, wenn sich die zugrunde liegenden Daten ändern

Wenn ich die ungültigen Daten jedoch über den Befehl, den das Ansichtsmodell bereitstellt, in gültige Daten umwandelt, wird die Zeilenüberprüfungsregel nur erneut ausgelöst, wenn die aktuelle Zeile in DataGrid den Fokus verliert. Daher können die angezeigten Daten tatsächlich gültig sein, aber die DataGrid zeigt immer noch ein rotes Ausrufezeichen mit ungültigen Daten an. Dies bleibt der Fall, bis die aktuelle Zeile den Fokus verliert oder ich wieder gültige Daten eingib.

Wie erzwinge ich eine zweite Validierung der aktuellen Zeile? Ich habe bereits ValidatesOnTargetUpdated="True" gesetzt, aber das hat das Problem nicht gelöst. Ich habe auch die INotifyPropertyChanged-Schnittstelle implementiert, aber das hat das Problem auch nicht behoben.

Lösung

Als Benutzer mm8 darauf hingewiesen, INotifyDataErrorInfo ist der Ansatz zu gehen. Ich habe die Zeilenüberprüfungsregel entfernt und eine Eigenschaft mit dem Namen HasErros in meinem Ansichtsmodell verfügbar gemacht, die die HasErrors-Eigenschaft meines Modells repliziert, die wiederum INotifyDataErrorInfo implementiert. Als nächstes habe ich eine benutzerdefinierte RowValidationErrorTemplate

<DataGrid.RowValidationErrorTemplate> 
    <ControlTemplate> 
     <Grid> 
      <Ellipse Width="12" Height="12" Fill="Red"/> 
      <Label Content="!" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" 
        Foreground="White" FontSize="11"/> 
     </Grid> 
    </ControlTemplate> 
</DataGrid.RowValidationErrorTemplate> 

und erstellt den folgenden benutzerdefinierten Stil für DataGridRowHeader

<Style x:Key="MyDataGridRowHeaderStyle" TargetType="{x:Type DataGridRowHeader}"> 
    <!-- ... --> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type DataGridRowHeader}"> 
       <Border> 
        <Grid> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
         <Control SnapsToDevicePixels="True" 
           Template="{Binding ValidationErrorTemplate, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" 
           Visibility="{Binding Path=HasErrors, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/> 
        </Grid> 
       </Border> 
       <!-- ... --> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Hinweis von Visibility die Bindung. Die HasErrors-Eigenschaft ist die oben erwähnte Proxy-Eigenschaft.

Und schließlich, diesen Stil in der DataGrid verwenden als

<DataGrid RowHeaderStyle="{StaticResource MyDataGridRowHeaderStyle}" 
... 

Eine Implementierung BoolToVisibilityConverter folgt here gefunden werden kann.

Antwort

1

Statt das Hinzufügen eines ValidationRule zum RowValidationRules:

<DataGrid x:Name="dataGrid1" ItemsSource="{Binding Models}" DataContext="{Binding}"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="CellEditEnding" > 
      <i:InvokeCommandAction Command="{Binding PCommand}" 
            CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}"> 
      </i:InvokeCommandAction> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</DataGrid> 

in denen PCommand im Ansichtsmodell und Eigentum der DataGrid yo Sie können die Schnittstelle INotifyDataErrorInfo in der View-Modellklasse implementieren und das Ereignis ErrorChanged immer dann auslösen, wenn Sie den Status einer Zeile/eines Elements aktualisieren möchten.

Dies ist die MVVM-Methode zur Implementierung der Datenvalidierung. Die Verwendung einer ValidationRule ist nicht.

WPF 4.5: Überprüfen von Daten der INotifyDataErrorInfo Schnittstelle in Verwendung:https://social.technet.microsoft.com/wiki/contents/articles/19490.wpf-4-5-validating-data-in-using-the-inotifydataerrorinfo-interface.aspx

1

Sie können CellEditEnding handhaben, die Zeilen finden und UpdateSources der BindingGroup nennen:

private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) 
    { 
     DataGrid dg = sender as DataGrid; 
     foreach (var r in dg.Items) 
     { 
      DataGridRow row = dg.ItemContainerGenerator.ContainerFromItem(r) as DataGridRow; 
      if (row != null) 
       row.BindingGroup.UpdateSources(); 
     } 
    } 

Beachten Sie auch, zu UpdateSourceTrigger=PropertyChanged für Ihre Bindungen zu setzen.

bearbeiten

Beachten Sie, dass Sie auch EventTrigger verwenden können: von

private void DoPCommand(object parameter) 
    { 
     DataGrid dg = parameter as DataGrid; 
     if (dg != null) 
      foreach (var r in dg.Items) 
      { 
       DataGridRow row = dg.ItemContainerGenerator.ContainerFromItem(r) as DataGridRow; 
       if (row != null) 
        row.BindingGroup.UpdateSources(); 
      } 
    } 
Verwandte Themen