使用 MVVM 的 C# 泛型,将 T 从 中取出

2024-05-04

My Model是一个泛型类,包含(例如)Value属性可以是 int、float、string、bool 等。所以很自然地,这个类的表示形式如下Model<T>。为了收藏Model<T>实现接口IModel, 虽然IModel本身没有任何内容。

My ViewModel包含和实例Model<T>它是通过ViewModel的构造函数。我还想知道什么T位于 ViewModel 中,所以当我公开时Model to the View我知道的数据类型Model被埋了Value财产。 ViewModel 的类最终如下所示:

class ViewModel<T>
{
   private Model<T> _model;

   public ViewModel(Model<T> model) { ....blah.... }

   public T ModelsValue {get; set; }

}

这工作正常,但有限制。所以现在我需要公开一组IModels随着变化的Ts to my View,所以我试图建立一个ObservableCollection of new ViewModel<T>s到不断变化的列表IModels。问题是,我不知道如何获得T from Model<T> from IModel构建ViewModel<T>(Model<T>)在运行时。

在 VS2010 调试器中,我可以将鼠标悬停在任何IModel对象并查看其完整内容Model<int>例如在运行时,所以我知道数据在那里。

有任何想法吗?


这是我用于视图模型集合的内容:

Preface:

您的视图模型对象可以是弱类型的。给IModel财产object Value {get;}并将其暴露在ModelViewModel : ViewModel<IModel>你用于所有人IModel对象(参见我的ViewModel<T>实施如下)。如果你有多种组合ObservableCollection<IModel>, ICollection<Model<T>>等等,这里显示的框架是一个救星。如果您仍然需要通用视图模型,您可以派生一个ModelViewModel<T> : ModelViewModel这需要一个Model<T>在它的构造函数中。创建适当类型的逻辑将进入传递给的转换器ViewModelCollection.Create below. 请注意,这种设计会造成性能损失。

ModelViewModel CreateModelViewModel(IModel model)
{
    Type viewModelType = typeof(ModelViewModel<>).MakeGenericType(model.Type);
    ModelViewModel viewModel = Activator.CreateInstance(viewModelType, model);
    return viewModel;
}

用法示例:

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

好处:

  • 使用惰性实现来允许树中的高效甚至递归绑定。
  • 视图模型集合仅实现INotifyCollectionChanged如果底层模型集合实现INotifyCollectionChanged.

类概述(链接到 github 的完整实现):

  • ViewModel<TModel> http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ViewModel%601.cs:我的视图模型类的基类。暴露了一个Model我在视图模型的支持代码中使用的属性。

  • ObservableViewModelCollection<TViewModel, TModel> http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ObservableViewModelCollection%602.cs: Lazy(实际上目前还没有,但绝对应该是),可观察到的从模型到视图模型的映射。实施INotifyCollectionChanged.

  • ViewModelCollection<TViewModel, TModel> http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ViewModelCollection%602.cs: Lazy从 TModel 集合映射到TViewModel.

  • ViewModelCollection http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ViewModelCollection.cs:静态助手 - 返回一个ICollection<TViewModel>, using ObservableViewModelCollection<TViewModel, TModel>当源集合实现时INotifyCollectionChanged,否则使用ViewModelCollection<TViewModel, TModel>.

一些可能对您的视图模型集合有用的额外类型:

ConcatCollection:与 ViewModelCollection 一样,这包括一个静态帮助器来自动选择适当的实现。 ConcatCollection 通过直接绑定到源集合来连接集合。

  • ConcatCollection http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ConcatCollection.cs
  • ConcatCollection<T> http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ConcatCollection%601.cs
  • ObservableConcatCollection<T> http://github.com/280Z28/Application-Foundations/blob/master/Mvvm/ObservableConcatCollection%601.cs

这是我如何使用这种类型来公开的示例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> 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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 MVVM 的 C# 泛型,将 T 从 中取出 的相关文章

  • ASP.NET Core Serilog 未将属性推送到其自定义列

    我有这个设置appsettings json对于我的 Serilog 安装 Serilog MinimumLevel Information Enrich LogUserName Override Microsoft Critical Wr
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • 从固定文档中删除页面?

    如何从固定文档中删除页面 我添加这样的页面 Add page to pageContent PageContent pageContent new PageContent IAddChild pageContent AddChild fix
  • WCF:将随机数添加到 UsernameToken

    我正在尝试连接到用 Java 编写的 Web 服务 但有些东西我无法弄清楚 使用 WCF 和 customBinding 几乎一切似乎都很好 除了 SOAP 消息的一部分 因为它缺少 Nonce 和 Created 部分节点 显然我错过了一
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐