我正在创建MVVM应用程序,并且在“模型”部分中,我有简单的基础抽象类动物和类,它们从其派生而来:

public abstract class Animal
{
    public int Age { get; set; }
}

public class Dog : Animal
{
    public string Name { get; set; }
}

ViewModel部分包含UI友好的 VM 其中的类:
public abstract class AnimalVM<T> : ViewModelBase where T : Animal
{
    protected readonly T animal;

    public int Age
    {
        get { return animal.Age; }
        set
        {
            animal.Age = value;
            OnPropertyChanged("Age");
        }
    }

    protected AnimalVM(T animal)
    {
        this.animal = animal;
    }
}

public class DogVM : AnimalVM<Dog>
{
    public string Name
    {
        get { return animal.Name; }
        set
        {
            animal.Name = value;
            OnPropertyChanged("Name");
        }
    }

    public DogVM(Dog dog) : base(dog) { }
}

假设我还有另一个 VM 类,其中包含ObservableCollection<AnimalVM>。问题是如何创建允许我在其中存储不同类型的动物的那种属性?我想实现以下目标:
public class AnimalListVM : ViewModelBase
{
    // here is a problem, because AnimalVM<Animal> isn't compatible with DogVM
    readonly ObservableCollection<AnimalVM<Animal>> animals;
    public ObservableCollection<AnimalVM<Animal>> Animals
    {
        get { return animals; }
    }

    public AnimalListVM(IList<Animal> animals)
    {
        //this.animals = ...
    }
}

我可以将ObservableCollection<AnimalVM<Animal>>属性更改为ICollection属性,然后使用一些词典Animal-> AnimalVM包装器和Activator.CreateInstance()创建 AnimalVM 列表-它可以工作,但是当我尝试扩展AnimalListVM时添加另一个属性SelectedAnimal,它将在示例 View 中绑定(bind)到例如DataGrid控件我对这种类型的属性SelectedItem有另一个问题。它不能是AnimalVM<Animal>类型,因为当我的Collection中有 DogVM 对象时,它将不适合此操作并引发异常。

如果只有非通用的AnimalVM,但我不想在派生自AnimalVM的每个DogVM,CatVM,BirdVM类中复制和粘贴类似的属性,一切都会清楚。我该如何实现?

最佳答案

好的,我找到了一个解决方案,它当然非常简单:只需为您的通用抽象基类创建另一个非通用抽象基类,然后从该新创建的非通用类派生您的通用类。在这种情况下,您还必须将属性从非泛型类重写为泛型类(更具体地重写它们),但是您只需执行一次,因此不必在每个泛型派生的ViewModel中复制和粘贴相同的代码。 (在我们的示例中,每个DogVM,CatVM,BirdVM等)。

关于mvvm - 通用ViewModel类的ObservableCollection,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4207019/

10-10 18:25