Windows Forms(WinForms)模型视图视图模型模式(MVVM)是否要使用数据绑定?

7
首先,我并不生气,因为我在WinForms中使用了MVVM模式。我知道MVP(Model View Presenter)模式及其变种。当我开始这个项目时,我打算学习WPF并使用它,但是我被迫加快程序开发速度,没有时间学习WPF,所以我必须在我熟悉的WinForms中编写它。
简而言之,我有一个大型数据导向的智能客户端应用程序,接近完成,我已经完成了所有的Models和ViewModels(基础设施、领域、表示层都完成了),UI也完成了,现在我只需要将UI连接到ViewModels。
首先,我使用标准的winforms方式进行连接(BindingSources和简单的数据绑定),但是当我完成30-50%的绑定后,我发现我的程序运行非常缓慢,到目前为止,我总共有100-150个绑定属性,其中30个是领域根实体(聚合根)绑定到其编辑表单。因此,在这种情况下,数据绑定效果不佳,会出现许多不必要的更新,当某些小东西发生变化时整个视图级联更新,行为不明确,以及其他丑陋的东西。这听起来像是非常不可靠的代码,我对此几乎没有控制权。
因此,我开始将连接重写为纯净的WinForms代码(订阅PropertyChange和ListChanged事件,并从UI上自己设置ViewModels属性)。需要编写很多代码,但它运行得更快,我对此有完全的控制权,感觉更加可靠。
那么,你们对此有什么想法?有人有过这样的经历吗?你们对于“是否使用数据绑定”有什么看法?

1
请参见https://dev59.com/BnRB5IYBdhLWcg3wV196#682216,了解与Windows窗体一起实现MVC的相关内容。 - Ian Ringrose
3个回答

6

您可能想要查看Truss。它提供了一种在POCO上工作的WPF风格绑定管理器。这使得在Windows Forms中使用MVVM变得更加有效。


不需要 - 它们直接在实现INPC的POCO上工作。这非常流畅。 - Reed Copsey
这里有人知道所有这些模式的好学习资源吗?我感觉我也得在这方面想出一些解决方案。顺便说一下,这是我最近提出的一个问题:http://stackoverflow.com/questions/26132035/custom-logic-in-windows-forms-data-binding - Eduardo Wada
如果想要MVVM样式的绑定,建议使用WPF——它比Windows Forms更加优美。@EduardoWada - Reed Copsey
我已经有了 Windows Forms 代码,因此更希望进行 Windows Forms 的重构或仅仅是开发新控件的新样式,即使它不像 WPF 那样好看,但我希望有一些可以进行测试自动化的架构。 - Eduardo Wada
@EduardoWada 一般来说,使用WPF并嵌入ElementHost会更好。WinForms与MVVM不兼容... - Reed Copsey
显示剩余4条评论

2
另一种可能性是在WinForms中使用继承的BindingSource组件进行数据绑定。例如:http://ingebrigtsen.info/2010/08/31/mvvm-in-windows-forms/。即使在.NET CF环境下也可以平稳运行。
我已经修改了实现以达到两个目标:
  • 通过WinForms设计器为我的ViewModel提供简单的数据绑定支持
  • 使用control.Invoke实现多线程支持,因为默认的BindingSource不支持它。现在它会对来自后台线程的PropertyChanged事件做出反应。
这是我的简单ViewModelBindingSource类:
public class ViewModelBindingSource : BindingSource
{
    private readonly Control _control = new Control();
    private object _viewModel;
    private Type _viewModelType;

    public ViewModelBindingSource()
    {
    }

    public ViewModelBindingSource(IContainer container)
        : base(container)
    {
    }

    public ViewModelBindingSource(object dataSource, string dataMember)
        : base(dataSource, dataMember)
    {
    }

    public object ViewModel
    {
        get { return _viewModel; }
        set { _viewModel = value; }
    }

    public Type ViewModelType 
    { 
        get { return _viewModelType; }
        set
        {
            if (value != null)
            {
                // save the type of our viewmodel
                _viewModelType = value;
                // create an instance of our viewmodel - so we don't need codebehind
                _viewModel = Activator.CreateInstance(_viewModelType);
                // add the viewmodel instance to the internal IList collection of the bindingsource
                Add(_viewModel);
                // move to the first element
                MoveFirst();
                // set the datasource of the binding source to the first element
                // this is necessary for data binding of all windows forms controls
                DataSource = this[0];
            }
        }
    }

    /// <summary>
    /// Pass the call to the main thread for windows forms
    /// This is needed for multithreading support.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnListChanged(ListChangedEventArgs e)
    {
        if (_control != null && _control.InvokeRequired)
            _control.Invoke(new Action<ListChangedEventArgs>(OnListChanged), e);
        else
        {
            base.OnListChanged(e);
        }
    }

1

在WinForms中使用数据绑定真的很痛苦,订阅INotifyPropertyChanged事件并手动执行操作也是过度设计。我非常喜欢MVVM,即使在WinForms上也因为其出色的可测试性和可维护性,但不希望以写3倍代码的代价来实现。因此,对于新代码,我现在使用组合的View+ViewModel。


当你说“组合视图+视图模型”时,你是指将属性放在表单代码后面,然后将其用作对象数据源吗?我正在考虑这样做。 - The Muffin Man
你的程序运行缓慢是因为默认情况下,BindingSource 会更新所有 ViewModel 的属性,即使只有一个在视图中被更改。在视图中的 DataBinding 上使用 DataSourceUpdateMode.Never,并在 ViewModel 的属性上使用 NotifyPropertyChanged,这样就可以控制数据绑定了。 - Fabio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接