避免在 MVVM 模型中使用 ObservableCollection

Rom*_*mbé 3 c# wpf mvvm

我有一个包含集合的 Model 类和该 Model 类的 ViewModel 包装器类。包装器类INotifyPropertyChanged为模型类中的每个属性实现并具有一个包装器属性。我以这种方式实现它是为了使模型类尽可能独立于任何 WPF 命名空间,因为这些类也在另一个项目(Windows 服务)中使用。实现(简化)如下所示:

模型

public class FbiDirectory
{
    private string type;
    private ObservableCollection<PluginValue> pluginValues = new ObservableCollection<PluginValue>();

    public string Type
    {
        get
        {
            return this.type;
        }

        set
        {
            this.type = value;
        }
    }

    public ObservableCollection<PluginValue> PluginValues
    {
        get
        {
            return this.pluginValues;
        }

        set
        {
            this.pluginValues = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型包装器

public class FbiDirectoryViewModel : INotifyPropertyChanged
{
    private FbiDirectory fbiDirectory = new FbiDirectory();

    public string Type
    {
        get
        {
            return this.fbiDirectory.Type;
        }

        set
        {
            this.fbiDirectory.Type = value;

            this.OnPropertyChanged("Type");
            this.OnPropertyChanged("Title");
        }
    }

    public ObservableCollection<PluginValue> PluginValues
    {
        get
        {
            return this.fbiDirectory.PluginValues;
        }

        set
        {
            this.fbiDirectory.PluginValues = value;

            this.OnPropertyChanged("PluginValues");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是是否有一种方法可以使PluginValues模型类型中的集合仍然具有ViewModel 中List的功能。ObservableCollection也许使用某种转换器或铸造或类似的东西。

Bra*_*ner 6

您始终可以将模型类保留为常规类List<>,并将视图模型上的匹配属性设置为ObservableCollection<>. 我经常这样做,没有任何问题。在视图模型的构造函数(将模型作为参数)中,我只是ObservableCollection<>根据模型上的属性内容实例化视图模型。如果您实际上也包装了该属性,那么这种方法尤其有效Type

当模型属性更改时,您不会自动更新视图模型属性,因此您必须自己保持同步,但无论如何,我认为视图模型工作的一部分,特别是当您包装您想要的模型时不控制。

public void MyViewModel(MyModel<MyModelPropertyType> model)
{
    MyListProperty = new ObservableCollection<MyWrappedModelPropertyType>(model.ModelListProperty.Select(i => new MyWrappedModelPropertyType(i));
}
Run Code Online (Sandbox Code Playgroud)

如果不需要包装属性类型,则可以省略 LINQ。您最终会因复制列表而产生实例化时间和内存成本方面的一些开销。如果您需要包装属性类型,那么无论如何您最终都会这样做。