本文介绍了MVVM的C#泛型,将T拉出&lt; T&gt;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 My $ b 我的 ViewModel 包含和$ Model< T> ,它通过 ViewModel 的构造函数传入。我仍然想知道ViewModel中的 T 是什么,所以当我将 Model 暴露给查看我知道模型的埋藏值属性的数据类型。 ViewModel的类最终如下所示: class ViewModel< T> {私人模特< T> _模型; public ViewModel(Model< T> model){.... blah ....} public T ModelsValue {get;组; } } 这很好,但是有限。因此,现在我需要将 IModels 的集合以 Ts 变更为我的 View code>,所以我试图设置 ObservableCollection new ViewModel< T> s< / code>更改为 IModels 的更改列表。问题是,我无法弄清楚如何从 Model 从在运行时构建 ViewModel< T>(Model< T>)< 在VS2010调试器中,我可以对任何 IModel 对象进行鼠标悬停,并查看完整的模型< int> 所以我知道数据在那里。 任何想法? 解决方案以下是我用于查看模型集合的内容: 前言: 您的视图模型对象可以是弱类型的。给> IModel 一个属性 object Value {get;} ,并在 ModelViewModel:ViewModel< ;用于所有 IModel 对象的IModel> (请参阅我的 ViewModel< T> 执行如下)。如果您有 ObservableCollection< IModel> , ICollection< Model< T>>< / code>等各种组合,这里展示的框架是一个救星。如果您仍然需要通用视图模型,则可以派生 ModelViewModel< T> :ModelViewModel ,它在构造函数中使用 Model< T> 。创建适当类型的逻辑将转换为传递给下面的 ViewModelCollection.Create 的转换器。 ModelViewModel CreateModelViewModel(IModel模型) { Type viewModelType = typeof(ModelViewModel<>)。MakeGenericType(model.Type); ModelViewModel viewModel = Activator.CreateInstance(viewModelType,model); 返回viewModel; 用法示例: public class CatalogViewModel:ViewModel< ICatalog> { public CatalogViewModel(ICatalog目录):base(catalog) { Func< ICatalogProduct,ProductViewModel> viewModelFactory = CreateProductViewModel; this.Products = ViewModelCollection.Create(catalog.Products,viewModelFactory); } public ICollection< ProductViewModel>产品 { get; 私人套餐; } private ProductViewModel CreateProductViewModel(ICatalogProduct product) { return new ProductViewModel(product,this); $ / code $ / pre $ b $ h2优点:$ b​​ $ b 使用惰性实现来实现树中的高效甚至递归绑定。 视图模型集合仅实现 INotifyCollectionChanged 如果底层模型集合实现 INotifyCollectionChanged 。 类的概述(链接到github的完整实现): ViewModel< TModel> :我的视图模型类的基类。公开了我在视图模型的后台代码中使用的 Model 属性。 ObservableViewModelCollection< TViewModel,TModel> 懒惰(实际上当前不是,但肯定应该是),可观察从模型映射到视图模型。实现 INotifyCollectionChanged 。 ViewModelCollection< TViewModel,TModel> :从TModel集合到 TViewModel 的集合的映射。 ViewModelCollection code> :静态助手 - 使用 ObservableViewModelCollection< TViewModel,TModel>返回一个 ICollection< TViewModel> 当源集合实现 INotifyCollectionChanged ,否则使用 ViewModelCollection< TViewModel,TModel> 。 / b> 一些额外的类型可能对您的视图模型集合有用: Con catCollection :与ViewModelCollection类似,它包含一个静态助手来自动选择合适的实现。 ConcatCollection通过直接绑定到源集合来连接集合。 ConcatCollection ConcatCollection< T> ObservableConcatCollection< t> 下面是我如何使用这种类型向视图公开 Children 属性的示例,同时将我的可观察集合始终返回到原始源。 public class ProductViewModel:ViewModel< IProduct> { public ProductViewModel(IProduct product):base(product) { Func< IProduct,ProductViewModel> productViewModelFactory = CreateProductViewModel; Func< IRelease,ReleaseViewModel> releaseViewModelFactory = CreateReleaseViewModel; this.Products = ViewModelCollection.Create(product.Products,productViewModelFactory); this.Releases = ViewModelCollection.Create(product.Releases,releaseViewModelFactory); this.Children = ConcatCollection.Create< object>((ICollection)this.Products,(ICollection)this.Releases); } public IList< ProductViewModel>产品 { get; 私人套餐; } 公共IList< ReleaseViewModel>发布 { get; 私人套餐; } public IEnumerable< object>儿童 { get; 私人套餐; $ b $ private ProductViewModel CreateProductViewModel(IProduct product) { return new ProductViewModel(product); private ReleaseViewModel CreateReleaseViewModel(IRelease release) { return new ReleaseViewModel(release); } } My Model is a generic class that contains a (for example) Value property which can be int, float, string, bool, etc. So naturally this class is represented something like Model<T>. For the sake of collections Model<T> implements the interface IModel, although IModel is itself empty of any content.My ViewModel contains and instance of Model<T> and it is passed in through ViewModel's constructor. I still want to know what T is in ViewModel, so when I expose Model to the View I know the datatype of Model's buried Value property. The class for ViewModel ends up looking like the following:class ViewModel<T>{ private Model<T> _model; public ViewModel(Model<T> model) { ....blah.... } public T ModelsValue {get; set; }}This works fine, but is limited. So now I need to expose a collection of IModels with varying Ts to my View, so I'm trying to set up an ObservableCollection of new ViewModel<T>s to a changing list of IModels. The problem is, I can't figure out how to get T from Model<T> from IModel to construct ViewModel<T>(Model<T>) at runtime.In the VS2010 debugger I can mouseover any IModel object and see its full Model<int> for example at runtime so I know the data is in there.Any ideas? 解决方案 Here's what I'm using for view model collections:Preface:Your view model objects can be weakly typed. Give IModel a property object Value {get;} and expose that in a ModelViewModel : ViewModel<IModel> that you use for all IModel objects (see my ViewModel<T> implementation below). If you have various combinations of ObservableCollection<IModel>, ICollection<Model<T>>, etc., the framework shown here is a lifesaver. If you still need generic view model, you can derive a ModelViewModel<T> : ModelViewModel that takes a Model<T> in its constructor. The logic to create the appropriate type would go in the converter passed to ViewModelCollection.Create below. Do be warned that this design will impose a performance penalty.ModelViewModel CreateModelViewModel(IModel model){ Type viewModelType = typeof(ModelViewModel<>).MakeGenericType(model.Type); ModelViewModel viewModel = Activator.CreateInstance(viewModelType, model); return viewModel;}Example usage:public class CatalogViewModel : ViewModel<ICatalog>{ public CatalogViewModel(ICatalog catalog) : base(catalog) { Func<ICatalogProduct, ProductViewModel> viewModelFactory = CreateProductViewModel; this.Products = ViewModelCollection.Create(catalog.Products, viewModelFactory); } public ICollection<ProductViewModel> Products { get; private set; } private ProductViewModel CreateProductViewModel(ICatalogProduct product) { return new ProductViewModel(product, this); }}Benefits:Uses lazy implementations to allow for efficient and even recursive bindings in trees.The view model collections only implement INotifyCollectionChanged if the underlying model collection implements INotifyCollectionChanged.Overview of the classes (full implementations linked to github):ViewModel<TModel>: Base class for my view model classes. Exposes a Model property that I use in the view model's backing code.ObservableViewModelCollection<TViewModel, TModel>: Lazy (actually not currently, but definitely should be), observable mapping from a model to a view model. Implements INotifyCollectionChanged.ViewModelCollection<TViewModel, TModel>: Lazy mapping from a collection of TModel to a collection of TViewModel.ViewModelCollection: Static helper - returns an ICollection<TViewModel>, using ObservableViewModelCollection<TViewModel, TModel> when the source collection implements INotifyCollectionChanged, otherwise using ViewModelCollection<TViewModel, TModel>.A few extra types that might be useful for your view model collections:ConcatCollection: Like ViewModelCollection, this includes a static helper to automatically choose an appropriate implementation. The ConcatCollection concatenates collections by binding directly to the source collection(s).ConcatCollectionConcatCollection<T>ObservableConcatCollection<T>Here is an example of how I used this type to expose a Children property to the view while maintaining my observable collections all the way to back to the original source.public class ProductViewModel : ViewModel<IProduct>{ public ProductViewModel(IProduct product) : base(product) { Func<IProduct, ProductViewModel> productViewModelFactory = CreateProductViewModel; Func<IRelease, ReleaseViewModel> releaseViewModelFactory = CreateReleaseViewModel; this.Products = ViewModelCollection.Create(product.Products, productViewModelFactory); this.Releases = ViewModelCollection.Create(product.Releases, releaseViewModelFactory); this.Children = ConcatCollection.Create<object>((ICollection)this.Products, (ICollection)this.Releases); } public IList<ProductViewModel> Products { get; private set; } public IList<ReleaseViewModel> Releases { get; private set; } public IEnumerable<object> Children { get; private set; } private ProductViewModel CreateProductViewModel(IProduct product) { return new ProductViewModel(product); } private ReleaseViewModel CreateReleaseViewModel(IRelease release) { return new ReleaseViewModel(release); }} 这篇关于MVVM的C#泛型,将T拉出&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-16 23:13