调用SetProperty时不触发OnPropertyChanged

时间:2014-12-09 12:30:16

标签: vb.net prism

我使用的是Prism 5和Visual Basic,但我想C#中的解决方案对我来说也是有效的。

我遇到的问题是这段代码运行正常:

Private Property _nombreEnvio As String
Public Property nombreEnvio As String
    Get
        Return _nombreEnvio
    End Get
    Set(value As String)
        SetProperty(_nombreEnvio, value)
        OnPropertyChanged("nombreEnvio")
    End Set
End Property

但是如果我删除调用OnPropertyChange的行,它就不会更新视图中的字段:

Private Property _nombreEnvio As String
Public Property nombreEnvio As String
    Get
        Return _nombreEnvio
    End Get
    Set(value As String)
        SetProperty(_nombreEnvio, value)
        ' THIS CODE DOES NOT REFRESH THE VIEW
    End Set
End Property

假设SetProperty调用应该调用OnPropertyChanged,但事实并非如此。它有一个奇怪的行为,它用最后一个值更新视图。我解释自己,因为它很复杂:

  • 如果nombreEnvio是CARLOS,我将其设置为PEDRO,它不会更新视图,它仍会显示CARLOS。
  • 如果我将其设置为ANTONIO,则会在视图中显示PEDRO
  • 如果我将其设置为MIGUEL,则会在视图中显示ANTONIO
  • 等等......总是最后一个值,而不是现在设定的值

只需添加OnPropertyChanged行,它就可以正常工作。

任何人都可以解释我为什么会这样?

非常感谢

2015年1月30日更新 我创建了一个新的VB项目(名为TestPrismVB),安装了Prism并编写了这个简单的代码:

Imports Microsoft.Practices.Prism.Mvvm

Public Class pruebaViewModel
    Inherits BindableBase

    Private Property _oneProperty As String
    Public Property oneProperty As String
        Get
            Return _oneProperty
        End Get
        Set(value As String)
            SetProperty(_oneProperty, value)
            'IF I UNCOMMENT THIS LINE, IT WORKS:
            'OnPropertyChanged("oneProperty")
        End Set
    End Property

    Private Property _anotherProperty As String
    Public Property anotherProperty As String
        Get
            Return _anotherProperty
        End Get
        Set(value As String)
            SetProperty(_anotherProperty, value)
            oneProperty = value
        End Set
    End Property
End Class

XAML文件是MainWindow.xaml:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:TestPrismVB"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:pruebaViewModel/>
    </Window.DataContext>
    <StackPanel>
        <TextBox Text="{Binding anotherProperty, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBlock Text ="{Binding oneProperty}"/>
    </StackPanel>
</Window>

如果您运行此简单项目,并键入1234,您将看到TextBlock后退一步(它将显示123而不是1234)。

这是一个VB错误吗?棱镜虫?我做错了吗?

谢谢

1 个答案:

答案 0 :(得分:3)

好吧,我现在可以帮到你。我不是Visual Basic开发人员,因此我没有在代码中看到“错误”,但是经验丰富的VB.NET专家可以在5分钟内帮助您。

因此,Prism和Visual Basic完全按照应有的方式完成所有事情,问题是由您的代码引起的,而且这一行是由它负责的:

Private Property _oneProperty As String

SetProperty()方法接受属性存储ByRef,但您提供属性作为存储。在这种情况下,当您将属性作为ByRef参数传递时,VB会将属性值复制到临时变量,并传递变量 ByRef并将变量中的值分配给属性。

观察到的行为有一个简单的解释:Prism引发PropertyChanged事件和WPF绑定请求新的属性值就在之前它将由VB从临时变量分配实际上已通过ByRef

TL; DR 解决方案是:

替换此

Private Property _oneProperty As String
Private Property _anotherProperty As String

用这个

Private _oneProperty As String
Private _anotherProperty As String