如何使用 CollectionView 收听 INotifyDataErrorInfo
How to listen to INotifyDataErrorInfo using a 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}">
其中 Nodes 是包含 ListCollectionView 的自定义 ObservableCollection
:
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
我想要发生的是让 CollectionView
中的个人 Node
通知 ListView
,以便它突出显示无效的个人条目(即有一个NodeResults
无效)在屏幕上。
我的第一直觉是 Node 不知何故需要订阅并冒泡 NodeResults
' ErrorsChanged
事件,因此 ObservableValidatableModelBase
[=58 上的 BubbleErrorsChanged
方法=] - 但这似乎不起作用。
另一种可能性是 - ListView 甚至有用于显示验证异常的默认模板吗?如果没有,这样的事情应该有效吗? (不是...)
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="{Binding Path=(Validation.Errors).CurrentItem, Converter={StaticResource ValidationExceptionToColourConverter}}"/>
</Style>
</ListView.ItemContainerStyle>
其中 ValidationExceptionToColourConverter
只需 returns Brushes.Red 或 Brushes.White 取决于错误是否为 Nothing
。
注意:将文本框直接绑定到 Nodes.NodeResults.SomeProperty 效果很好,给出了我期望的结果。
我需要以下内容:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="{Binding Path=HasErrors, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToBrushConverter}}"/>
</Style>
</ListView.ItemContainerStyle>
我有以下场景:
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}">
其中 Nodes 是包含 ListCollectionView 的自定义 ObservableCollection
:
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
我想要发生的是让 CollectionView
中的个人 Node
通知 ListView
,以便它突出显示无效的个人条目(即有一个NodeResults
无效)在屏幕上。
我的第一直觉是 Node 不知何故需要订阅并冒泡 NodeResults
' ErrorsChanged
事件,因此 ObservableValidatableModelBase
[=58 上的 BubbleErrorsChanged
方法=] - 但这似乎不起作用。
另一种可能性是 - ListView 甚至有用于显示验证异常的默认模板吗?如果没有,这样的事情应该有效吗? (不是...)
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="{Binding Path=(Validation.Errors).CurrentItem, Converter={StaticResource ValidationExceptionToColourConverter}}"/>
</Style>
</ListView.ItemContainerStyle>
其中 ValidationExceptionToColourConverter
只需 returns Brushes.Red 或 Brushes.White 取决于错误是否为 Nothing
。
注意:将文本框直接绑定到 Nodes.NodeResults.SomeProperty 效果很好,给出了我期望的结果。
我需要以下内容:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="{Binding Path=HasErrors, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToBrushConverter}}"/>
</Style>
</ListView.ItemContainerStyle>