如何优雅地反序列化View-Model的一部分,而不是丢失以前的数据绑定?

时间:2014-10-29 14:46:15

标签: c# wpf mvvm data-binding viewmodel

我的ViewModel

public class MyViewModelType {
    public PlayerElements Player { get; set; }
    .
    .
    .
}

PlayerElements包含许多可绑定属性:

public class PlayerElements : INotifyPropertyChanged {
    ObservableCollection<IEntity> Angles { get; set; }
    .
    .
    .
    ObservableCollection<IBuilding> Castles { get; set; }

    public string PlayerName { get; set; }
}

当我反序列化已保存的模型时,我会这样做:

    public MyViewModelType ViewModel { get; set; }

    public LoadPlayerFromDisk(SomeDataModel dm){
        ViewModel.Player = new PlayerElements(vm.PlayerData);
    }

问题很明显:当我创建新的PlayerElements时,我失去了所有绑定。我目前的解决方案是清除所有列表并手动添加:

ViewModel.Player.Angles.Clear();
foreach (var angel in vm.PlayerData.Angles)
    ViewModel.Player.Angles.Add(angel);
不用说 - 可怕的解决方案......

我想到的另一个选择是使用大剂量的反射将所有事件处理程序复制到新对象。它是同一类型的坏解决方案:我需要遍历整个树(ObservableCollection<T>的属性,每个项目实现INotifyPropertyChanged,并且可以有更多ObservableCollection<T>类型的子项,依此类推...)

那么如何优雅地反序列化视图模型,而不会丢失所有绑定?

1 个答案:

答案 0 :(得分:1)

除非您没有为绑定引擎提出必要的属性更改通知以查看您的属性分配,否则您没有理由丢失绑定。从您粘贴的代码中可以看出这种情况。

您的属性设置者需要提升PropertyChanged公开的INotifyPropertyChanged事件,例如:

public class MyViewModelType : INotifyPropertyChanged {
    private PlayerElements _player;

    public PlayerElements Player {
        get { return _player; }
        set { 
            _player = value;
            OnPropertyChanged("Player");
        }
    }
    .
    .
    .
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName) {
        var handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName);
    }
}

当绑定收到Player已更改的通知时,它将自动取消订阅具有绑定的子属性的通知,并订阅新Player的子属性。您不必自己复制任何活动订阅。