【问题标题】:Tracking the CurrentChanged event of an ICollectionView declared as a dependencyProperty跟踪声明为 dependencyProperty 的 ICollectionView 的 CurrentChanged 事件
【发布时间】:2014-12-20 11:50:19
【问题描述】:

我有一个这样声明的 ICollectionView;

Public Shared ReadOnly DataIcvProperty As DependencyProperty = DependencyProperty.Register("DataIcv", GetType(ICollectionView), GetType(DataNavigator), New PropertyMetadata(Nothing))


<Description("The CollectionView (as an ICollectionView) to be passed to the DataNavigator control"), Category("Navigation Data Source")>
Public Property DataIcv As ICollectionView
    Get
        Return GetValue(DataIcvProperty)
    End Get
    Set(ByVal Value As ICollectionView)
        SetValue(DataIcvProperty, Value)

    End Set
End Property

我想在其上跟踪 CurrentChanged 事件。因此,在 wpf userControl 的构造函数中(其中声明了此属性,我添加了以下内容:

AddHandler DataIcv.CurrentChanged, AddressOf OnDataICVCurrentChanged

然后添加以下内容

Public Sub OnDataICVCurrentChanged(ByVal sender As Object, e As EventArgs) Handles internalIcv.CurrentChanged

    'Do whatever needs doing when the record in the ICollectionView changes

End Sub

当我编译用户控件并在单独的项目中使用它时,我在控件的构造函数中的 AddHandler 行上收到 NullReferenceException(没有任何内部异常详细信息)。

我需要做些什么来跟踪 DataIcv 的当前 Changed 事件,以便我的用户控件的元素可以正确响应这些更改?

谢谢

编辑

这与我描述的here 的问题有关。本质上,我希望导航器控件能够反映最终用户可以独立于导航器选择网格上的行这一事实。

【问题讨论】:

    标签: wpf vb.net dependency-properties


    【解决方案1】:

    问题是,当您尝试在构造函数中订阅 CurrentChanged 事件时,DependencyProperty DataIcvProperty 具有默认值 Nothing(正如您在属性注册中指定的那样) .所以NullReferenceException

    您可以使用PropertyChangeCallback 解决此问题(请参阅documentation)。

    我来自 C# 世界,无法保证 VB.NET 的语法正确,但这种方法肯定会奏效:

    Public Shared ReadOnly DataIcvProperty As DependencyProperty =
    DependencyProperty.Register("DataIcv",
        GetType(ICollectionView), GetType(DataNavigator),
        New FrameworkPropertyMetadata(
            Nothing,
            New PropertyChangedCallback(AddressOf OnDataIcvChanged)))
    

    那你需要实现OnDataIcvChanged这个静态方法,每次属性值改变都会调用。

    Private Shared Sub OnDataIcvChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If e.OldValue IsNot Nothing
            RemoveHandler (e.OldValue As ICollectionView).CurrentChanged, AddressOf OnDataICVCurrentChanged
        EndIf
        If e.NewValue IsNot Nothing
            AddHandler (e.NewValue As ICollectionView).CurrentChanged, AddressOf OnDataICVCurrentChanged
        EndIf
    End Sub
    

    更新: 如果您的事件处理程序方法不是静态的,那么您应该通过对象实例访问它:

    Private Shared Sub OnDataIcvChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim DataNavigator instance = d As DataNavigator        
        If e.OldValue IsNot Nothing
            RemoveHandler (e.OldValue As ICollectionView).CurrentChanged, AddressOf instance.OnDataICVCurrentChanged
        EndIf
        If e.NewValue IsNot Nothing
            AddHandler (e.NewValue As ICollectionView).CurrentChanged, AddressOf instance.OnDataICVCurrentChanged
        EndIf
    End Sub
    

    编辑:最终起作用的代码:

     Public Shared ReadOnly DataIcvProperty As DependencyProperty = DependencyProperty.Register("DataIcv", GetType(ICollectionView), GetType(DataNavigator), New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnDataIcvChanged)))
    
    
    <Description("The CollectionView (as an ICollectionView) to be passed to the DataNavigator control"), Category("Navigation Data Source")>
    Public Property DataIcv As ICollectionView
        Get
            Return CType(GetValue(DataIcvProperty), ICollectionView)
        End Get
        Set(ByVal Value As ICollectionView)
            SetValue(DataIcvProperty, Value)
    
        End Set
    End Property
    
    Private Shared Sub OnDataIcvChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim dn As DataNavigator = CType(d, DataNavigator)
    
    
    
        If e.OldValue IsNot Nothing Then
            RemoveHandler dn.DataIcv.CurrentChanged, AddressOf dn.OnDataICVCurrentChanged
        End If
        If e.NewValue IsNot Nothing Then
            AddHandler dn.DataIcv.CurrentChanged, AddressOf dn.OnDataICVCurrentChanged
        End If
    
    End Sub
    
    Private Sub OnDataICVCurrentChanged(ByVal sender As Object, ByVal e As EventArgs)
    
        Record.Text = (DataIcv.CurrentPosition + 1).ToString
    
    End Sub
    

    【讨论】:

    • 您好,非常感谢您的解释。我有一个与您的 OnDataIcvChanged Sub 有关的问题。如果没有对依赖对象本身的引用(即 DataNavigator 控件),那么第一行可能会将 Dim dn 设置为 DataNavigator = Ctype(d,DataNavigator)。如果是这种情况,我们应该如何编写删除和添加处理程序行,它们应该引用依赖对象(dn)。
    • 是的,当然。如果您的 OnDataICVCurrentChanged 方法不是静态的,那么您需要一个对象实例来添加或删除事件订阅。所以你可以改变静态的OnDataIcvChanged 方法来访问相关的对象。
    • 好吧,我设法获得了可编译的 vb 代码,但这仅在实际集合更改时触发,而不是在选择其中的不同项目时触发。我在问题的底部发布了一个链接,该链接与我提出的问题相关,这是我要解决的问题的根本原因。
    • 您是否将网格的IsSynchronizedWithCurrentItem 属性设置为True
    • 嗨,我终于意识到我做错了什么,并对代码进行了轻微更改,我已将其添加为您的答案下方的编辑,现在我已将其标记为正确并已回答。在经历了一天半的沮丧之后,我非常感谢你为我指明了正确的直接方向。
    猜你喜欢
    • 1970-01-01
    • 2015-01-17
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多