0

次のシナリオがあります。

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 は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、無効な (無効な がある) 個々のエントリがNodeResults画面上で強調表示されるようにすることです。

NodeResults私の最初の本能は、Node が'ErrorsChangedイベントにサブスクライブしてバブリングする必要があるためBubbleErrorsChanged、クラスのメソッドObservableValidatableModelBaseが必要であるということですが、それは機能していないようです。

別の可能性は - ListView には検証の例外を表示するためのデフォルトのテンプレートもありますか? そうでない場合、このようなものが機能する必要がありますか? (そうではありません...)

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

エラーが発生したかどうかに応じて、 Brushes.RedValidationExceptionToColourConverterまたは Brushes.White を返すだけNothingです。

注: テキスト ボックスを Nodes.NodeResults.SomeProperty に直接バインドしても問題なく動作し、期待どおりの結果が得られます。

4

1 に答える 1

0

以下が必要でした:

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="Background" Value="{Binding Path=HasErrors, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToBrushConverter}}"/>
    </Style>
</ListView.ItemContainerStyle>  
于 2016-08-17T15:16:56.273 に答える