wpf – 属性与变量为ByRef参数
我创建了一个实现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 然后我有一个类,应该保存一些数据.为简单起见,它只包含一个属性(在本例中). Public Class Item Public Property Text As String End Class 然后我有一个继承自基类并使用数据保持类的第三个类.第三个类应该是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 然后我有我的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> 如您所见,此窗口仅包含两个TextBox和一个按钮. TextBoxes绑定到属性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,编译器会看到属性的getter,因此它将首先调用_text1的Get属性,然后将引用传递给返回值作为参数.因此,当您的函数SetProperty正在接收ByRef参数时,它是来自getter的返回值,而不是实际的字段值. 根据我的理解here,如果你说你的属性是ByRef,编译器将在你退出函数调用时自动更改字段引用…这样就可以解释为什么它在你的事件发生后会发生变化…… This other blog似乎证实了这种奇怪的行为. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |