0

У меня есть следующий сценарий:Как слушать INotifyDataErrorInfo используя CollectionView

XAML:

<ListView Name="lsv_edit_selectNode" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" 
    Grid.RowSpan="17" IsSynchronizedWithCurrentItem="True" SelectionMode="Single" 
    ItemsSource="{Binding Path=Nodes.CollectionView, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"> 

Где Вершины обычай ObservableCollection, который содержит ListCollectionView:

Public Class FilterableObservableCollection(Of T) 
    Inherits ObservableCollection(Of T) 
    Implements INotifyPropertyChanged, INotifyCollectionChanged 
    Public Property CollectionView As ListCollectionView 
     Get 
      Return _collectionView 
     End Get 
     Protected Set(value As ListCollectionView) 
      If value IsNot _collectionView Then 
       _collectionView = value 
       NotifyPropertyChanged() 
      End If 
     End Set 
    End Property 
    'etc. 

T в этот случай - объект Node, со многими свойствами, включая тот, который мне интересен (назовите его NodeResults):

Public Class Node 
    Inherits ObservableValidatableModelBase 
     Public Property NodeResults as NodeResults 
      Set 
       SetAndNotify(_nodeResults, Value) ' INotifyPropertyChanged 
      AddHandler _nodeResults.ErrorsChanged, AddressOf BubbleErrorsChanged ' INotifyDataErrorInfo? 
      End Set 
     End Property 
     ' etc. 

и NodeResults:

Public Class NodeResults 
    Inherits ObservableValidatableModelBase 

     ' many properties here, each validated using custom Data Annotations. This works, when I bind a text box directly to here, for example. 

ObservableValidatableModelBase Реализует INotifyDataErrorInfo и сохраняет свои ошибки в коллекции под названием errors:

Private errors As New Dictionary(Of String, List(Of String))() 
Public ReadOnly Property HasErrors As Boolean Implements INotifyDataErrorInfo.HasErrors 
    Get 
     Return errors.Any(Function(e) e.Value IsNot Nothing AndAlso e.Value.Count > 0) 
    End Get 
End Property 

Public Function GetErrors(propertyName As String) As IEnumerable Implements INotifyDataErrorInfo.GetErrors 
    Try 
     If Not String.IsNullOrEmpty(propertyName) Then 
      If If(errors?.Keys?.Contains(propertyName), False) _ 
       AndAlso If(errors(propertyName)?.Count > 0, False) Then ' if there are any errors, defaulting to false if null 
       Return errors(propertyName)?.ToList() ' or Nothing if there are none. 
      Else 
       Return Nothing 
      End If 
     Else 
      Return errors.SelectMany(Function(e) e.Value.ToList()) 
     End If 
    Catch ex As Exception 
     Return New List(Of String)({"Error getting errors for validation: " & ex.Message}) 
    End Try 
End Function 

Public Event ErrorsChanged As EventHandler(Of DataErrorsChangedEventArgs) Implements INotifyDataErrorInfo.ErrorsChanged 

Public Sub NotifyErrorsChanged(propertyName As String) 
    ErrorsChangedEvent?.Invoke(Me, New DataErrorsChangedEventArgs(propertyName)) 
End Sub 

Public Sub BubbleErrorsChanged(sender As Object, e As DataErrorsChangedEventArgs) 
    If TypeOf (sender) Is ObservableValidatableModelBase Then 
     errors = DirectCast(sender, ObservableValidatableModelBase).errors 
    End If 
    NotifyErrorsChanged(String.Empty) 
End Sub 

То, что я хочу, чтобы это произошло для отдельных Node с в CollectionView, чтобы уведомить ListView, чтобы он выделял людей al, которые недействительны (т. введите NodeResults, что недействительно) на экране.

Моего первый инстинкт, что Node-то нужно, чтобы подписаться на и пузырь на NodeResults 'ErrorsChanged события, следовательно BubbleErrorsChanged метода на ObservableValidatableModelBase класса - но это не похож на работу.

Другая возможность - есть ли в ListView даже шаблон по умолчанию для отображения исключений проверки? Если нет, должно ли что-то вроде этой работы? (Это не ...)

<ListView.ItemContainerStyle> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="Background" Value="{Binding Path=(Validation.Errors).CurrentItem, Converter={StaticResource ValidationExceptionToColourConverter}}"/> 
    </Style> 
</ListView.ItemContainerStyle> 

Где ValidationExceptionToColourConverter просто возвращает Brushes.Red или Brushes.White в зависимости от того, является ли ошибка Nothing или нет.

Примечание: привязка текстового поля непосредственно к узлам.NodeResults.SomeProperty работает нормально, давая результаты, которые я ожидаю.

ответ

0

мне нужно было следующее:

<ListView.ItemContainerStyle> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="Background" Value="{Binding Path=HasErrors, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToBrushConverter}}"/> 
    </Style> 
</ListView.ItemContainerStyle>