通知ViewModel上的所有属性都已更改

时间:2011-05-20 15:30:01

标签: mvvm-light

我正在使用MVVM Light Toolkit的V3 SP1开发Silverlight应用程序。

我的申请完全是法语/英语。所有UI元素(按钮,标签等)和所有数据(模型)。我需要动态语言切换,这是完全实现的,适用于来自资源文件的任何内容。我正在努力的是ViewModels。

模型具有特定于语言的属性(DescriptionEn,DescriptionFr)和一个附加属性调用LocalizedDescription,它使用当前区域性来返回调用特定于语言的属性。

当语言发生变化时(通过按钮点击),我举起并广播(通过Messenger)一个属性更改事件。

在我的每个ViewModel中,我注册接收语言交换的属性更改消息。

我想通知ViewModel的所有属性已发生变化。

来自:http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx

  

PropertyChanged事件可以通过使用null或String.Empty作为PropertyChangedEventArgs中的属性名来指示对象上的所有属性都已更改。

但是,由于工具包使用RaisePropertyChanged(...)抽象了已更改事件的引发,因此我无法使其工作。我还检查了takeit的源代码并发现RaisePropertyChanged调用VerifyPropertyName(..)而后者返回错误,该属性不属于ViewModel。我还注意到VerifyPropertyName方法属于Conditional(“DEBUG”),但即使我选择Release配置,仍然会引发ArgumentException(“找不到属性”)。

除了为ViewModel的每个属性手动调用RaisePropertyChanged之外,有没有人知道如何使用工具包使用它?

随访:

基于Simon的评论,我试图创建自己的类来扩展ViewModelBase。我查看了CodePlex上的源代码,并决定创建一个名为RaiseAllPropertyChanged()的方法。它只是RaisePropertyChanged(字符串propertyName)的副本,但没有参数,也没有调用VerifyPropertyName(...)。我无法让它发挥作用。这就是我所拥有的。

public class ViewModelBaseExtended : ViewModelBase
{
    protected void RaiseAllPropertyChanged()
    {
        var handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(String.Empty));
        }
    }
}

但是我收到编译错误:The event 'GalaSoft.MvvmLight.ViewModelBase.PropertyChanged' can only appear on the left hand side of += or -=。这是ViewModelBase中使用的代码的副本。

有人可以就如何让它发挥作用提出一些建议吗?

解决方案:

我将ViewModelBase中的所有代码复制到一个新类中。然后我添加了上面提到的方法RaisePropertyChanged(),该方法使用PropertyChangedEventArgs实例化String.Empty类。现在这是我的ViewModels的新子类。

再次感谢西蒙领导的方式!

3 个答案:

答案 0 :(得分:2)

不幸的是,目前的MVVMLight代码库

是不可能的

短期内你有两个选择

  1. 用户自己的自定义基类。自定义基类我的意思是“不要从MVVMLight类继承”

  2. 在发布模式下下载并编译MVVMLight。这将强制排除“VerifyPropertyName”方法。当然,你没有得到财产名称检查的价值。

  3. 我相信Laurent Bugnion很快就会解决这个问题。

答案 1 :(得分:2)

如果您在2016年阅读此内容,则可以使用ObservableObject并通过执行以下操作通知所有属性已更改:

RaisePropertyChanged(string.Empty);

答案 2 :(得分:1)

解决此问题的一个较轻的解决方案是覆盖类中的RaisePropertyChanged(string propertyName):

protected override void RaisePropertyChanged(string propertyName)
    {
        if (propertyName != null)
        {
            base.RaisePropertyChanged(propertyName);
        }
        else
        {
            var handler = PropertyChangedHandler;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(null));
            }

        }
    }