Nos*_*omo 6 vb.net wpf byref inotifypropertychanged
我创建了一个实现INotifyPropertyChanged接口的基类.此类还包含一个通用函数,SetProperty用于设置任何属性的值并在PropertyChanged必要时引发事件.
Public Class BaseClass
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Function SetProperty(Of T)(ByRef storage As T, value As T, <CallerMemberName> Optional ByVal propertyName As String = Nothing) As Boolean
If Object.Equals(storage, value) Then
Return False
End If
storage = value
Me.OnPropertyChanged(propertyName)
Return True
End Function
Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional ByVal propertyName As String = Nothing)
If String.IsNullOrEmpty(propertyName) Then
Throw New ArgumentNullException(NameOf(propertyName))
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
然后我有一个类,应该保存一些数据.为简单起见,它只包含一个属性(在本例中).
Public Class Item
Public Property Text As String
End Class
Run Code Online (Sandbox Code Playgroud)
然后我有一个继承自基类并使用数据保持类的第三个类.第三个类应该是WPF窗口的ViewModel.
我没有列出RelayCommand该类的代码,因为你可能都有自己的实现.请记住,当执行命令时,此类执行给定的函数.
Public Class ViewModel
Inherits BaseClass
Private _text1 As Item 'data holding class
Private _text2 As String 'simple variable
Private _testCommand As ICommand = New RelayCommand(AddressOf Me.Test)
Public Sub New()
_text1 = New Item
End Sub
Public Property Text1 As String
Get
Return _text1.Text
End Get
Set(ByVal value As String)
Me.SetProperty(Of String)(_text1.Text, value)
End Set
End Property
Public Property Text2 As String
Get
Return _text2
End Get
Set(ByVal value As String)
Me.SetProperty(Of String)(_text2, value)
End Set
End Property
Public ReadOnly Property TestCommand As ICommand
Get
Return _testCommand
End Get
End Property
Private Sub Test()
Me.Text1 = "Text1"
Me.Text2 = "Text2"
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
然后我有我的WPF窗口,它使用ViewModel类DataContext.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Text1}" Height="24" Width="100" />
<TextBox Text="{Binding Text2}" Height="24" Width="100" />
<Button Height="24" Content="Fill" Command="{Binding TestCommand}" />
</StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
如您所见,此窗口仅包含两个TextBox和一个按钮.TextBox绑定到属性Text1,Text2按钮应该执行命令TestCommand.
当命令被执行这两个属性Text1和Text2给定的值.由于两个属性都会引发PropertyChanged事件,因此这些值应该显示在我的窗口中.
但是我的窗口中只显示值"Text2".
属性的值Text1是"Text1",但似乎PropertyChanged在属性获取其值之前引发了此属性的事件.
有没有办法SetProperty在我的基类中更改函数以PropertyChanged在属性获得其值后引发?
谢谢您的帮助.
到底发生了什么?
这不起作用,因为属性的行为与字段不同。
当您Me.SetProperty(Of String)(_text2, value)这样做时,会发生的情况是传递对该字段的引用_text2而不是其值,因此该SetProperty函数可以修改引用内的内容,并且该字段也会被修改。
但是,当您这样做时Me.SetProperty(Of String)(_text1.Text, value),编译器会看到属性的 getter,因此它将首先调用_text1 的 Get 属性,然后将对返回值的引用作为参数传递。因此,当您的函数SetProperty接收ByRef参数时,它是 getter 的返回值,而不是实际的字段值。
根据我在这里的理解,如果你说你的属性是 ByRef,编译器会在你退出函数调用时自动更改字段引用...这样就可以解释为什么它在你的事件后发生变化...
其他博客似乎证实了这种奇怪的行为。
| 归档时间: |
|
| 查看次数: |
441 次 |
| 最近记录: |