【问题标题】:Is it possible to override the Parameter keyword, or create a new Keyword, for observable properties?是否可以为可观察属性覆盖 Parameter 关键字或创建新关键字?
【发布时间】:2016-12-01 17:31:14
【问题描述】:

在 VB.NET(不引用 3rd-party 库)中,我发现我正在编写大量以下代码:

Private _prop as String = "test"
Public Property Prop As String
  Get
    Return _prop
  End Get
  Set(value As String)
    _prop = value
    NotifyPropertyChanged()
  End Set

'(add more properties here...)

Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub NotifyPropertyChanged(<CallerMemberName> Optional propertyName As String = "")
    If PropertyChangedEvent IsNot Nothing Then
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End If
End Sub

我想做的是这样的:

Public ObservableProperty Prop As String = "test"

并让 ObservableProperty 成为我定义的结构,它可以完成所有样板文件。

我知道如果我不希望它成为 Observable,我可以使用相同的模式 (Public Property NonObsProp As String = "test"),那么是否也可以让它们自动成为 observable?

【问题讨论】:

  • 该问题的答案使用了我想避免的第 3 方库
  • 很遗憾,您的问题的答案是否定的。不过你们相处得很好。我们中的许多人都希望有一个更简单的内置解决方案。 (也请看这里:stackoverflow.com/questions/3347309/…
  • 曾经有人提议允许属性有{Get, Set, Notify}来处理这些事情,但MS拒绝了。
  • @sstan,您在链接中引用的SetProperty 想法(@crea7or)很棒!它删除了真正有用的样板文件,我认为我将得到最接近的答案。如果你想写出来,我会给你答案 - 否则我会自己写。

标签: .net vb.net properties observable


【解决方案1】:

受 Knockout.js 启发,减少 INPC 属性样板的一种可能方法是定义可观察值类型。

Imports System.ComponentModel

Public Class ObservableValue(Of T)
    Implements INotifyPropertyChanging, INotifyPropertyChanged

    Public Event PropertyChanging As PropertyChangingEventHandler Implements INotifyPropertyChanging.PropertyChanging
    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Private Shared ReadOnly __changing As PropertyChangingEventArgs = New PropertyChangingEventArgs("Value")
    Private Shared ReadOnly __changed As PropertyChangedEventArgs = New PropertyChangedEventArgs("Value")

    Public Sub New()
    End Sub

    Public Sub New(initialValue As T)
        _value = initialValue
    End Sub

    Private _value As T
    Public Property Value As T
        Get
            Return _value
        End Get
        Set(newValue As T)
            If Not EqualityComparer(Of T).Default.Equals(_value, newValue) Then
                RaiseValueChanging()
                _value = newValue
                RaiseValueChanged()
            End If
        End Set
    End Property

    Public Sub RaiseValueChanging()
        RaiseEvent PropertyChanging(Me, __changing)
    End Sub

    Public Sub RaiseValueChanged()
        RaiseEvent PropertyChanged(Me, __changed)
    End Sub

    Public Overrides Function ToString() As String
        Return If(_value IsNot Nothing, _value.ToString(), String.Empty)
    End Function

    Public Shared Widening Operator CType(value As T) As ObservableValue(Of T)
        Return New ObservableValue(Of T)(value)
    End Operator

End Class

然后可以使用它来定义属性 - 类不一定需要实现 INotifyPropertyChanged,除非出于其他原因需要。

Public Class MyViewModel
    Public ReadOnly Property Prop1 As ObservableValue(Of String) = "A"
    Public ReadOnly Property Prop2 As ObservableValue(Of Boolean) = False
End Class

然后您需要记住在获取/设置值时访问.Value 属性(ReadOnly 有帮助,也许还有一种更优雅的方式来公开底层值),例如在 WPF 绑定中:

vm.Prop1.Value = "NewValue"
<TextBlock Text="{Binding Prop1.Value}"/>

我还没有充分利用这种模式来发现缺点……甚至是与典型 INPC 模式相比的优点。

【讨论】:

    【解决方案2】:

    @sstan 的评论为我指明了正确的方向。这不是一个完美的答案,但这是我目前能得到的最接近的答案。

    本质上,它是引用here 的方式,它建议创建一个调用NotifyPropertyChangedSetProperty 方法,从而减少样板代码。

    类似:

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value))
            {
                return false;
            }
    
            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2020-08-09
      • 2016-02-11
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      相关资源
      最近更新 更多