是否有任何理由使用通用视图模型,虽然我们不能在xaml中应用它们

本文关键字:xaml 不能 我们 应用 理由 任何 是否 模型 视图 | 更新日期: 2023-09-27 18:05:55

根据这个问题和来自好人的非常有用的答案,我发现XAML中不支持泛型类型。我们不允许为我们的用户控件实例化通用视图模型。但是,根据这个事实,我决定提出另一个问题:

  1. 为什么我们要创建一个通用视图模型,当我们不能在视图?我们必须为每种类型定义具体的类拥有泛型类到底有什么好处?一开始我试过通用的视图模型,因为我认为可以自定义视图根据输入的参数。并使用类型化方法处理WPF组分的含量。
  2. 人们建议我为每个类型创建一个基本通用视图模型和几个子具体类。在这种情况下,泛型类的用途是什么?据我所知,视图模型是一个用于绑定到数据上下文的概念。所以,如果没有办法访问这些类型的参数在DataContext为什么我应该使用一个通用的视图模型,因为没有其他用途的视图模型?因为应用程序的所有逻辑和业务都在模型的中心。视图模型只为视图准备模型中数据的表示。
  3. 为什么微软没有在XAML中提供这个功能?在WPF中开发这样的功能有什么限制吗?或者类似的东西,实际上是与MVVM的本质相矛盾的逻辑吗?

是否有任何理由使用通用视图模型,虽然我们不能在xaml中应用它们

我能理解你的沮丧,但我认为这里对MVVM模式存在误解:

  1. 一个通用的类将是有用的,如果你有很多视图模型之间的共享功能。然而,在MVVM中,ViewModels意味着比MVC更复杂(和不同)。它们与服务对话,充当GUI与底层/代码/业务逻辑等之间的粘合剂。实际上,可以使用DI/IoC使用通用视图模型,只需注入ViewModelBase并将其设置为数据上下文,最好是在构造函数中。根据您使用的IoC容器,您只需要向它注册您的类型。然而,您需要的视图模型的所有代码都在该基类中是非常可疑的-这意味着没有特定于某个视图模型的代码!我怀疑你把MVVM视图模型与MVC视图模型混淆了,这是我见过的常见错误。

  2. 这是我认为你误解了MVVM模式中的ViewModel的部分。

,因为应用程序的所有逻辑和业务都位于模型的中心。View Model只是为View准备Model中数据的表示。

  • (续)它做这些事情,但它处理从视图回调到业务逻辑和模型(RelayCommands, DataBindings是双向的)。它还会在创建视图时加载数据。所以不要把MVVM中的视图模型误认为只是一个从ModelClass到ModelClassForViewBinding的转换器。

  • 可能有一些技巧你可以应用,使其工作。然而,我们大多数人从来没有遇到过这个问题。我的猜测是,这将需要对标记和附加功能进行太多的更改,而收益却很少。由于上述原因,不是与MVVM相矛盾。

  • 我能描述视图模型的最简短的方式是,它更类似于MVP模式中的Presenter。它是元素根的DataContext。它编排所有所需数据的加载。它通过RelayCommands处理来自视图的调用,包括按钮点击、文本更改、焦点丢失等,并将它们转换为方法调用,通过服务和存储库将其转换为业务逻辑。一个简单的只读视图模型可以像这样:

    [ImplementPropertyChanged]
    public class CustomerViewModel : ViewModelBase<Customer>
    {
        public bool IsBusy { get; private set; }
        private ICustomerRepository _customerRepository;
        private IWindowService _windowService;
        [Inject]
        public CustomerViewModel(ICustomerRepository customerRepository, IWindowService windowService)
        {
            _customerRepository = customerRepository;
            _windowService = windowService;
            LoadData();
        }
        private async void LoadData()
        {
            IsBusy = true;
            try 
            {
                // Customer would be in your base, as public T BusinessObject { get; protected set; }
                BusinessObject = await _customerRepository.GetSelectedCustomer();
            }
            catch (Exception err)
            {
                _windowService.ShowErrorWindow(err);
            }
            finally
            {
                IsBusy = false;
            }
        }
    }
    

    这将是可视根(UserControl或类似)的数据上下文。没有办法把所有的逻辑应用到ViewModelBase或类似的东西上。这就是为什么我怀疑这是对模式的误解。