C# 如何将列表转换为隐式运算符类型

C# 如何将列表转换为隐式运算符类型,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我试图学习MVVM,在我的ViewModel中,我添加了隐式操作符,它将模型转换为ViewModel,反之亦然,但现在的问题是如何将模型列表转换为ViewModel列表 下面是我尝试用于列表转换的结构代码,但它不起作用: Person.cs class Person { public string FirstName { get; set; } public string LastName { get; set; } } PersonViewModel.cs class Pe

我试图学习MVVM,在我的ViewModel中,我添加了隐式操作符,它将模型转换为ViewModel,反之亦然,但现在的问题是如何将模型列表转换为ViewModel列表

下面是我尝试用于列表转换的结构代码,但它不起作用:

Person.cs

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
PersonViewModel.cs

 class PersonViewModel : Person
{
    public string FullName { get; set; }

    public static implicit operator List<PersonViewModel>(IList<Person> person)
    {
        if (person == null)
            return null;

        return person.Select(c => new PersonViewModel(c)).ToList(); // This is not working

    }

    public static implicit operator PersonViewModel(Person person)
    {
        return new PersonViewModel
        {
            FirstName = person.FirstName,
            LastName = person.LastName,
        };
    }

    public static implicit operator Person(PersonViewModel personViewModel)
    {
        return new Person
        {
            FirstName = personViewModel.FirstName,
            LastName = personViewModel.LastName,
        };
    }

}
类PersonViewModel:Person
{
公共字符串全名{get;set;}
公共静态隐式运算符列表(ILST人员)
{
if(person==null)
返回null;
return person.Select(c=>newPersonViewModel(c)).ToList();//这不起作用
}
公共静态隐式运算符PersonViewModel(Person)
{
返回新PersonViewModel
{
FirstName=person.FirstName,
LastName=person.LastName,
};
}
公共静态隐式运算符Person(PersonViewModel PersonViewModel)
{
换人
{
FirstName=personViewModel.FirstName,
LastName=personViewModel.LastName,
};
}
}
尝试使用Cast

person.Cast<PersonViewModel>().ToList();
person.Cast().ToList();
更新

这将给您带来其他错误。您可以使用扩展方法,并在需要时显式调用。类似这样的情况(确保最终检查空值)

班级人员
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
类PersonViewModel:Person
{
公共字符串全名{get;set;}
}
静态类转换助手
{
公共静态Person-ToPerson(此PersonViewModel pvm)
{
返回新人()
{
FirstName=pvm.FirstName,
LastName=pvm.LastName
};
}
公共静态PersonViewModel TopPersonViewModel(此人p)
{
返回新的PersonViewModel()
{
FirstName=p.FirstName,
LastName=p.LastName
};
}
公共静态IEnumerable TopPersonViewModels(IEnumerable persons)
{
返回persons.Select(p=>p.ToPersonViewModel());
}
}
很抱歉,您的“MVVM模式”对我来说似乎有点奇怪。
这是我对MVVM模式的理解

编辑作为@Mark Feldman评论的答案
若包装看起来不必要或代码膨胀,那个么可以跳过“ModelWrapper”,并且可以由模型本身实现
INotifyPropertyChanged
。 如果您不关心向视图通知模型属性的更改,则不需要将模型集合转换为ViewModels集合。
ViewModel将包含ObservableCollection类型的属性

class PersonViewModel
{
    public ObservableCollection<Person> Persons { get; set; }

    //if you don't care about tracking changes of collection(Add, Remove)
    //then use only List<Person> without any conversions
   public List<Person> Persons { get; set; }

}

然后通过构造函数以同样的方式将模型列表转换为ViewModel集合

Ok这可能是个愚蠢的问题,但您是否缺少“新”关键字?@ViktorLaCroix编辑了我的帖子,但这次它抱怨“PersonViewModel不包含带1个参数的构造函数”它是否包含接受1个参数的构造函数D如果不是,并且您不希望这样,那么您应该执行类似person.Select(x=>newpersonviewmodel(){FullName=c.FullName})的操作@ViktorLaCroix和c.FullName来自哪里?@zee这是你的代码,不是我们的。啊,我的错,编辑了我的帖子。现在给出的错误是“PersonViewModel不包含接受1个参数的构造函数”。啊,好的:)更新了我的答案。但是,我认为最终会出现更多错误,因为您不能在那里使用该接口,并且可以在基类之间定义隐式运算符。tnx,我尝试过强制转换,但现在它抱怨“用户定义的转换必须转换为封闭类型或从封闭类型转换为封闭类型”。为什么要使用运算符重载,而不仅仅是创建一些映射帮助程序?我已经想过使用映射帮助程序,但我想当我有这么多模型和ViewModel时,维护起来会比较困难,因此,最好对每个ViewModel都使用隐式运算符,这将使代码看起来更干净。从我所能收集到的信息来看,问题不在于如何通过视图模型向视图公开模型属性,而在于如何保持视图模型集合与其关联的模型集合同步,而无需经历代码膨胀。我个人并不认为INPC是视图-模型-视图关系的唯一要求,因此我倾向于将其添加到模型中,同时用于属性和集合。在这之后,视图模型订阅其模型的CollectionChanged事件,同时仍按此处所示公开属性,这是一个简单的问题。@MarkFeldman,我创建包装器只是因为OP通过继承公开了从模型到视图模型的所有属性。如果您在评论中描述,请参见我的更新answer@MarkFeldman,据我所知,这个问题与同步模型的集合和viewmodel的集合无关,因为在另一种类型中转换一种类型(作为OP的方法)将始终创建新实例。
//Model
class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//ModelWrapper which implements INotifyPropertyChanged if Model doesn't
//Here you can add additional properties which will serve a View's needs
class PersonModelWrapper
{
    private Person _Model;

    //Through this constructor you will create instance of modelwrapper
    //without any conversions
    public PersonModelWrapper (Person model)
    {
        _Model = model;
    }

    public string FirstName 
    { 
        get 
        { 
            return _Model.FirstName; 
        }
        set 
        {
            _Model.FirstName = value; 
        }
    }
    public string LastName
    { 
        get 
        { 
            return _Model.LastName; 
        }
        set 
        {
            _Model.LastName = value; 
        }
    }
    public string FullName
    { 
        get 
        { 
            return _Model.FirstName + " " _Model.LastName; 
        }
    }

    //Through this property you will always access current model property
    //without conversions
    public Person Model { get { return _Model; }}
}

//ViewModel which used as DataContext in the View
class PersonViewModel
{
    private PersonModelWrapper _Wrapper;
    public string Wrapper
    { 
        get 
        { 
            return _Wrapper; 
        }
        set 
        {
            _Wrapper = value; 
        }
    }
}
class PersonViewModel
{
    public ObservableCollection<Person> Persons { get; set; }

    //if you don't care about tracking changes of collection(Add, Remove)
    //then use only List<Person> without any conversions
   public List<Person> Persons { get; set; }

}
public class PersonViewModel: INotifyPropertyCahnged
{
    private Person _Model;
    public Person Model
    {
        get { return _Model; }
        set
        {
            if(Equals(_Model, value) == true)
               return;
            _Model = value;
            this.RaisePropertyChanged();
        }

        public String FullName {get {return _ModelFirstName + " " + _Model.LastName; }}

        public PersonViewModel(Person model)
        {
            _Model = model;
        }
    }
}