开发者

ObservableCollection of generic ViewModel class

开发者 https://www.devze.com 2023-01-25 08:10 出处:网络
I\'m creating MVVM application and in Model section I have simple base abstract class Animal and class Dog which derives from it:

I'm creating MVVM application and in Model section I have simple base abstract class Animal and class Dog which derives from it:

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

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

ViewModel section containts UI-friendly VM classes of them:

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) { }
}

Suppose I have another VM class which contains ObservableCollection<AnimalVM>. The problem is how to create that kind of property which allow me to store there different types of Animal? I want to achieve something like this:

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 = ...            
    }
}

I can change ObservableCollection<AnimalVM<Animal>> property to ICollection property and then create list of AnimalVM using some dictionary Animal -> AnimalVM wrapper and Activator.CreateInstance() - it works but when I try to extend AnimalListVM adding another property SelectedAnimal which will be binded in sample View to e.g. DataGrid control I have another problem with type of that kind of property SelectedItem. It can't be of type AnimalVM<Animal> because when I have DogVM object in my Collection it won't fit with this and throw an exception.

Everything will be clear if only I had non-generic AnimalVM but I don't want to copy and paste similar properties in every DogVM, CatVM, 开发者_开发百科BirdVM class derived from AnimalVM. How can I achieve this?


Ok, I've found a solution and of course it's very simple: just create another, non-generic abstract base class for your generic abstract base class and then derive your generic class from that newly created non-generic class. In that case you also must rewrite properties from non-generic class to generic class (to be more specific override them), but you do this only once, so you don't have to copy and paste the same code in every generic derived ViewModel (in our example in every DogVM, CatVM, BirdVM, etc.).

0

精彩评论

暂无评论...
验证码 换一张
取 消