MvvmLight在Release版本中如何处理RaisePropertyChanged错误?

3

我遇到了一个奇怪的小错误,在MvvmLight v4 (.NET 4 build, v4.0.0.0/BL0016版本,通过NuGet安装)中出现。在我的项目中,有一个继承自 ViewModelBase 的视图模型表示在画布上绘制的可视元素。该视图模型具有典型的Top/Left/Width/Height属性,每个属性都调用 RaisePropertyChanged 方法。

public double Width
{
    get { return _width; }
    set
    {
        if (Math.Abs(_width - value) < DeltaEpsilon)
        {
            return;
        }

        _width = value;
        RaisePropertyChanged();
    }
}

针对不同的事件,视图模型还有一个方法,用于计算可视元素的位置和尺寸,并适当地设置属性:

public void CalculateSize()
{
    Width = DoSomeCalculation();
    // Calculate other settings...
}

我已经编写了一些单元测试来验证计算的正确性,当我在调试模式下运行时,测试可以正常运行。然而,如果我在发布模式下运行,测试将失败,并出现以下异常:

SetUp : System.InvalidOperationException : This method can only by invoked within a property setter.
at GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged()
at MyProject.ViewModels.TableViewModel.CalculateSize() in TableViewModel.cs: line 154

在TableViewModel的第154行,Width = DoSomeCalculation()这一行代码处出现了问题。换句话说,当我的方法试图设置属性值时,MvvmLight会抱怨我没有在属性setter内部调用RaisePropertyChanged方法。我尝试使用Reshaper的测试调试器进行调试,但是当我运行调试器时,测试通过了(即使已经处于Release模式下,可能在Resharper中调试单元测试会将其强制转换为Debug模式?)错误也会在应用程序本身中发生。
有什么想法,为什么Release模式会破坏代码?编译器优化代码的方式是否会破坏ObservableObject的RaisePropertyChanged()方法中对StackTrace的使用?请注意,上面的异常并没有显示Width setter被输入,它直接从CalculateSize方法跳到异常。

糟糕,刚刚发现了http://mvvmlight.codeplex.com/workitem/7520。那正是我的问题。 - David Keaveny
1个回答

3
如果你查看MVVM Light代码,你会发现RaisePropertyChanged()使用StackTrace来确定属性的名称。如此帖子所述,在发布模式下可能会有问题。
为了避免这个问题,可以使用不同的RaisePropertyMethod方法,你可以使用以下方法之一:
RaisePropertyChanged<YourClass>(x => x.Width);

或者
RaisePropertyChanged("Width");

这两种方法使用不同的方式来确定已更改的属性名称(第二种方法只使用属性名称)。


虽然我之前已经发布了一个链接,展示了我的问题的原因,但是既然你给了一个解决方法,我还是会给你答案的 :-) - David Keaveny
链接只是说有一个问题。在我的帖子中,我引用了另一篇 Stackoverflow 帖子,它实际上解释了为什么它不起作用。我还将这个问题指向了 Laurent,可以看 http://twitter.com/LBugnion/status/94173507906318337 获取他的回答。 - AxelEckenberger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接