IValueConverter仅在第一次显示数据绑定TreeView时被调用

时间:2013-12-28 01:00:57

标签: wpf treeview datatemplate ivalueconverter

我有一个绑定到ObservableCollection的TreeView(正确实现了IPropertyNotifyChanged)。每个TreeViewItem都是HierarchicalDataTemplate。我在TextBlock上有一个绑定到'amount'的转换器 - 如果字符串表示负数,则将前景颜色更改为红色。第一次加载TreeView时,所有数量都正确显示。但是,如果更改了基础ObservableCollection,则数量会正确更改,但颜色不会更改(即,负数'amount'显示为白色而不是红色)。

我尝试过同时使用IValueConverter和IMultiValueConverter。我确保一切都与UpdateSourceTrigger = PropertyChanged绑定。转换器就没有被调用。

每次“数量”发生变化时,我需要做什么才能调用转换器?

由于 安迪

模板:

<!-- Data templates-->
    <HierarchicalDataTemplate x:Key="RealTemplate" DataType="{x:Type l:Account}" ItemsSource="{Binding Path=children}">
        <DockPanel LastChildFill="True">
            <TextBlock x:Name="AccountTitle" Text="{Binding Path=title}" Foreground="White" DockPanel.Dock="Left"/>
            <TextBox x:Name="EditAccountTitle" Text="{Binding Path=title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource RoundedTextBox}" FontWeight="Bold" LostFocus="tvLostFocus" PreviewKeyDown="tvKeyDown" LostKeyboardFocus="tvLostFocus" Visibility="Collapsed" DockPanel.Dock="Left" l:FocusExtension.IsFocused="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" CaretIndex="{x:Static sys:Int32.MaxValue}"/>
            <TextBlock Text="{Binding Path=amount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right">
                <TextBlock.Foreground>
                    <MultiBinding Converter="{StaticResource GetColourConverterAmountM}" UpdateSourceTrigger="PropertyChanged">
                        <Binding/>
                    </MultiBinding>
                </TextBlock.Foreground>
            </TextBlock>
        </DockPanel>            
        <HierarchicalDataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=isEditable}" Value="True">
                <Setter TargetName="AccountTitle" Property="Visibility" Value="Collapsed"/>
                <Setter TargetName="EditAccountTitle" Property="Visibility" Value="Visible"/>                                        
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=isEditable}" Value="False">
                <Setter TargetName="AccountTitle" Property="Visibility" Value="Visible"/>
                <Setter TargetName="EditAccountTitle" Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource TreeViewTopItemConverter}}" Value="False">
                <DataTrigger.Setters>
                    <Setter Property="ContextMenu" Value="{StaticResource RealAccountMenu}"/>
                </DataTrigger.Setters>
            </DataTrigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource TreeViewTopItemConverter}}" Value="True">
                <DataTrigger.Setters>
                    <Setter Property="ContextMenu" Value="{StaticResource CategoryMenu}"/>
                </DataTrigger.Setters>
            </DataTrigger>
        </HierarchicalDataTemplate.Triggers>
    </HierarchicalDataTemplate>

转换器:

Public Class GetColourConverterAmountM
Implements IMultiValueConverter

Function Convert(ByVal values() As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As Globalization.CultureInfo) As Object Implements IMultiValueConverter.Convert

    If values Is Nothing Then
        Return New SolidColorBrush(Colors.White)
    ElseIf (Val(values(0).amount) >= 0) Then
        Return New SolidColorBrush(Colors.White)
    Else
        Return New SolidColorBrush(Colors.Red)
    End If
End Function

Function ConvertBack(ByVal value As Object, ByVal targetTypes() As Type, ByVal parameter As Object, ByVal culture As Globalization.CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
    Return Nothing
End Function
End Class

的ObservableCollection:

Public Class Account
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Private Sub NotifyPropertyChanged()
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Nothing))
End Sub

Private _name, _title, _amount, _target As String
Private _ID, _type, _category, _column As Integer
Private _isEditable, _isNodeExpanded, _isNodeSelected As Boolean
Private _children As ObservableCollection(Of Account)

Public Sub New(__ID As Integer, __name As String, __title As String, __amount As String, __target As String, __type As Integer, __category As Integer, __column As Integer)
    children = New ObservableCollection(Of Account)
    _ID = __ID
    _name = __name
    _title = __title
    _amount = __amount
    _target = __target
    _category = __category
    _type = __type
    _column = __column
    _isEditable = False
    _isNodeExpanded = True
    _isNodeSelected = False
End Sub

Property ID As Integer
    Get
        Return _ID
    End Get
    Set(value As Integer)
        _ID = value
        NotifyPropertyChanged()
    End Set
End Property

Property name As String
    Get
        Return _name
    End Get
    Set(value As String)
        _name = value
        NotifyPropertyChanged()
    End Set
End Property

Property title As String
    Get
        Return _title
    End Get
    Set(value As String)
        _title = value
        NotifyPropertyChanged()
    End Set
End Property

Property amount As String
    Get
        Return _amount
    End Get
    Set(value As String)
        _amount = value
        NotifyPropertyChanged()
    End Set
End Property

Property target As String
    Get
        Return _target
    End Get
    Set(value As String)
        _target = value
        NotifyPropertyChanged()
    End Set
End Property

Property category As Integer
    Get
        Return _category
    End Get
    Set(value As Integer)
        _category = value
        NotifyPropertyChanged()
    End Set
End Property

Property type As Integer
    Get
        Return _type
    End Get
    Set(value As Integer)
        _type = value
        NotifyPropertyChanged()
    End Set
End Property

Property column As Integer
    Get
        Return _column
    End Get
    Set(value As Integer)
        _column = value
        NotifyPropertyChanged()
    End Set
End Property

Property isEditable As Boolean
    Get
        Return _isEditable
    End Get
    Set(value As Boolean)
        _isEditable = value
        NotifyPropertyChanged()
    End Set
End Property

Property isNodeExpanded As Boolean
    Get
        Return _isNodeExpanded
    End Get
    Set(value As Boolean)
        _isNodeExpanded = value
        NotifyPropertyChanged()
    End Set
End Property

Property isNodeSelected As Boolean
    Get
        Return _isNodeSelected
    End Get
    Set(value As Boolean)
        _isNodeSelected = value
        NotifyPropertyChanged()
    End Set
End Property

Property children As ObservableCollection(Of Account)
    Get
        Return _children
    End Get
    Set(value As ObservableCollection(Of Account))
        _children = value
        NotifyPropertyChanged()
    End Set
End Property
End Class

1 个答案:

答案 0 :(得分:2)

您需要将TextBlock的Foreground属性绑定到amount,并使用转换器将amount转换为颜色。只要amount值发生变化,前景就会更新。例如(不使用多重绑定):

<TextBlock Text="{Binding Path=amount, Mode=TwoWay}"
           Foreground="{Binding Path=amount,
                           Converter="{StaticResource GetColourConverterAmount}" 
           DockPanel.Dock="Right" TextAlignment="Right">