【问题标题】:How to avoid a databinding / events hell on a complex screen?如何避免复杂屏幕上的数据绑定/事件地狱?
【发布时间】:2013-04-27 07:04:06
【问题描述】:

这更像是一个架构/设计问题。

过去我遇到过一些用 WPF/Windows 窗体等编写的项目,这些项目具有带有很多字段的复杂屏幕,并且这些字段相互连接(它们的值相互依赖,涉及一些逻辑)。

这些项目是我在实施后承担的,我发现很多事件/数据绑定地狱 - 我的意思是因为所有这些字段都依赖于其他他们已经实现 INotifyPropertyChanged 和其他字段结果修改。这会导致相同的字段在屏幕加载时更新 5-6 次,并且填充字段的顺序会导致可怕的错误。 (例如,Date 设置在 Job Type 之前,而不是在 Job Type 之后,所以我最终得到了不同的 Job Fee 。)

更糟糕的是,一些 hack 是在 UI 事件上实现的(例如,DropDown 更改为更新字段 X),而另一些则在 UI 绑定到的域模型中。

基本上,这是一个巨大的混乱,我只想知道如果我从头开始,实现这样的事情的最佳方法是什么。还是一开始就避免使用如此复杂的屏幕是个好主意?

【问题讨论】:

    标签: c# wpf winforms data-binding architecture


    【解决方案1】:

    我们有相当复杂的 UI(包括几个不同类型的相关字段,例如 DataGrid 中的行),MVVM 模式对我们来说效果很好。所有来自模型并暴露给视图的具有复杂逻辑相关的属性都被 ViewModel 中的等效属性“包装”,该属性没有支持字段,而是直接指向模型:

    public class SomeComplexViewModel
    {
    
        public SomeModel Model {get;set;}
    
        public string SomeCrazyProperty
        {
           get
           {
              return Model.SomeCrazyProperty;
           }
           {
              Model.SomeCrazyProperty = value;
              //... Some crazy logic here, potentially modifying some other properties as well.
           }
        }
    }
    
    <TextBox Text="{Binding SomeCrazyProperty}"/>
    

    这消除了“初始值”问题,因为Binding读取的初始值实际上是来自Model的真实值,因此放在Setter中的逻辑只有在需要时才会执行。

    然后,对于虚拟属性(其背后没有逻辑),我们直接从视图绑定到模型:

    <TextBox Text="{Binding Model.SomeRegularProperty}"/>
    

    这减少了 ViewModel 中的膨胀。

    关于后面代码中的事件,我完全避免这样做。我的文件隐藏代码几乎总是一个InitializeComponent(),仅此而已。

    只有 View-Specific 逻辑放在后面的代码中(例如动画等),当它不能直接在 XAML 中完成时,或者在代码中更容易完成时(大多数情况下并非如此) .

    编辑:

    值得一提的是,与基于 XAML 的绑定功能相比,winforms 绑定功能是个笑话。这可能是您在这些项目中看到那些可怕的混乱的原因吗?

    【讨论】:

      【解决方案2】:

      我会尽量将业务逻辑排除在属性设置器之外。

      首先,如果一个计算需要多个属性,我会编写一个执行计算的方法,并在适当的时候调用该方法。例如。如果属性值的所有不同组合都有意义,则可以只在每个属性的设置器中调用该方法,确保在任何一个属性更改时运行相同的代码。如果您只能评估属性值的特殊组合,您可以实现一个命令并让用户决定何时计算结果更改,或者您可以通过验证提供反馈,并且仅在组合有效时评估属性更改。如果有多个相互依赖的属性,我经常使用一个“ChangeInitiator”变量来指示哪些属性发生了变化,以便在计算方法中明确哪个属性负责更改以及其他哪些属性应该因此而更改。基本上,这与在每个属性设置器中执行一部分计算相同,但我发现如果关系的不同部分都在一个方法中,这有助于我保持对事物的概览。

      在我曾经写过的一个程序中,我会定期在后台线程上运行一些计算,所以每当需要进行新计算的数据发生变化时,我都会设置一个标志,并且每次都基于计时器进行所有更新秒左右...这也可以帮助您更直接地了解逻辑,并且避免为一组相关更改运行多次计算。

      关于更改通知,我真的会尝试仅将其用于 UI 数据绑定。

      【讨论】:

        猜你喜欢
        • 2020-10-15
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 2017-02-09
        • 2017-05-08
        • 2016-06-24
        • 2017-08-18
        • 2011-03-20
        相关资源
        最近更新 更多