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 S IN CollectionView通知ListView,以便突出顯示個人所有無效的條目(即有一個NodeResults是無效的)在屏幕上。

我的第一直覺是,不知何故節點需要訂閱和泡沫NodeResults'ErrorsChanged事件,因此在ObservableValidatableModelBaseBubbleErrorsChanged方法 - 但似乎並沒有工作。

另一種可能性是 - 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與否。

注意:將文本框直接綁定到Nodes.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>