【问题标题】:WPF Dependency Property - set from XAMLWPF 依赖属性 - 从 XAML 设置
【发布时间】:2019-12-04 18:03:51
【问题描述】:

我正在尝试在 WPF 个人理财应用中实现以下目标:

我想在不同的地方显示一个用户控件,提供资产持有的详细信息(通常是股票、债券等),目标资产可能会被用户动态更改,在这种情况下必须刷新控件。每个资产都有一个唯一标识符 AssetId。

我正在使用 MVVM,并且我开发了一个带有视图模型的单个窗口,该视图模型将 AssetID 作为参数(属性)并检索相关详细信息以绑定到视图。这工作很好。我想做的是制作一个具有相同功能的通用用户控件,这样我基本上可以将该“窗口”放在其他窗口中。

所以我几乎将该表单中的 XAML 复制粘贴到用户控件中,我正在努力将 AssetId 从父窗口传递到子控件。

Google 告诉我我需要一个依赖属性,这就是我所在的位置


Public Class HoldingView
    Private _AssetId As Integer
    Public AssetIdProperty As DependencyProperty = DependencyProperty.Register("AssetId",
                                                                                      GetType(Integer),
                                                                                      GetType(HoldingView),
                                                                                      New FrameworkPropertyMetadata(New PropertyChangedCallback(AddressOf AssetIDChanged)))
    Public Property AssetId As Integer
        Get
            Return GetValue(AssetIdProperty)
        End Get
        Set(value As Integer)
            SetValue(AssetIdProperty, value)
        End Set
    End Property
    Private Sub AssetIDChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
        Dim NewAssetId As Integer
        NewAssetId = e.NewValue
        Me.DataContext.AssetId = NewAssetId
    End Sub
    Public Sub New()

        ' This call is required by the designer.

        InitializeComponent()
        Me.DataContext = New HoldingViewmodel

    End Sub

End Class 

这样称呼:

<Grid>
    <local:HoldingView AssetId="{Binding AssetId}"/>
</Grid>

代码编译并运行,但是当我尝试加载具有用户控件的窗口时,应用程序崩溃并显示以下消息:

不能在“HoldingView”类型的“AssetId”属性上设置“绑定”。只能在 DependencyObject 的 DependencyProperty 上设置“绑定”。

这不是很有帮助。从我的谷歌搜索中,如果 DP 注册的语法不正确,您也可以收到此消息,但在我没有经验的情况下看起来不错...

其他人有这个吗?

【问题讨论】:

    标签: wpf vb.net xaml dependency-properties


    【解决方案1】:
    Public AssetIdProperty As DependencyProperty
    

    应该是

    Public Shared ReadOnly AssetIdProperty As DependencyProperty
    

    请看Custom Dependency Properties。

    同时删除

    Me.DataContext = New HoldingViewmodel
    

    因为这将有效地破坏任何基于 DataContext 的绑定,例如

    AssetId="{Binding AssetId}"
    

    源属性应该由继承的 DataContext 中的对象拥有,该对象通常是应用程序视图模型中的对象。

    控件不应该有自己的“私有”视图模型,而是处理代码中的属性更改。如果是 UserControl,则其 XAML 中的 UI 元素可能会绑定到 UserConrol 自己的属性。

    因此

    Me.DataContext.AssetId = NewAssetId
    

    在PropertyChangedCallback中是没有意义的,应该去掉,还有

    Private _AssetId As Integer
    

    总而言之,它应该是这样的:

    Public Class HoldingView
        Public Shared ReadOnly AssetIdProperty As DependencyProperty =
            DependencyProperty.Register(
                "AssetId",
                GetType(Integer),
                GetType(HoldingView),
                New FrameworkPropertyMetadata(
                    New PropertyChangedCallback(AddressOf AssetIdPropertyChanged)))
    
        Public Property AssetId As Integer
            Get
                Return GetValue(AssetIdProperty)
            End Get
            Set(value As Integer)
                SetValue(AssetIdProperty, value)
            End Set
        End Property
    
        Private Shared Sub AssetIdPropertyChanged(
            d As DependencyObject, e As DependencyPropertyChangedEventArgs)
            CType(d, HoldingView).AssetIdChanged(e.NewValue)
        End Sub
    
        Private Sub AssetIdChanged(id As Integer)
            ...
        End Sub
    
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class 
    

    【讨论】:

    • 耶!这就像做梦一样。非常感谢。因此,在重新教育自己从代码隐藏中删除(几乎)所有代码之后,我现在把它放回去了。考虑了一些,但最终一切都到位了。再次感谢克莱门斯。你是这个网站的一个很好的例子。
    猜你喜欢
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多