代码之家  ›  专栏  ›  技术社区  ›  James

如何在WinForms GUI控件和客户端类之间同步数据?

  •  2
  • James  · 技术社区  · 16 年前

    什么方法被认为是保持GUI控件中的数据结构与应用程序维护的数据结构同步的“标准”?

    例如: 在WinForms中,如果创建了一个ListView实例,而不是将其指向表示要在列表中显示的项的数据结构,则必须以编程方式实例化ListView项并调用.Add方法手动将它们逐个复制到ListView自身内部的数据结构中。从线程的角度来看,这是有意义的,而且在呈现控件的上下文中,也有意义的是,控件应该需要一个专门的数据结构来存在,而控件本身就知道维护的细节。

    然而,这产生了两个问题:

    冗余: 如果客户机类管理自己的实体列表,为了允许用户从WinForms UI中进行选择,必须通过以下方法读取、转换整个列表,然后在UI控件内部重新创建:添加(ListViewItem项)列表现在占用的内存是原来的两倍。

    复杂性: 由于现在存在两个列表,因此必须通过编程确保它们保持同步。这可以通过从客户机类的集合对象中激发的事件来实现,或者程序员在从另一个列表中添加/删除时,只需注意总是从一个列表中添加/删除。

    我见过许多这样的例子,程序员可以使用类似listview的ui元素作为维护列表的实际集合对象。例如,每个用户输入的项都将立即插入到ListView中,然后,当需要访问用户的实体时,应用程序只需遍历ListView。当您正确地将业务/应用程序逻辑与UI逻辑分离时,此方法无法应用。

    总的来说,在GUI控件内部的数据结构中存储应用程序数据似乎有点不对。同样,存储两个列表并保持它们的程序同步也不是一个很好的解决方案。理想情况下,只需要提供一个引用了客户机范围内的列表的UI元素。

    那么,解决这个问题的“正确”方法是什么?

    7 回复  |  直到 16 年前
        1
  •  3
  •   Grammarian    16 年前

    每个UI控件都需要自己的某种状态。对于复杂的控件(如ListView),状态也相应地复杂。诀窍是使控制状态的维护尽可能简单。使用标准的listview,这是不可能的——程序员必须完成这项工作。

    这就是我写作的原因之一 ObjectListView (围绕.NET WinForms ListView的开放源代码包装)。它允许您在更高级别上使用ListView,其中控件状态的维护是不可见的。对象列表视图直接对模型对象进行操作:

    this.objectListView1.Objects = listOfModelObjects;
    this.objectListView1.SelectedObject = aPerson;
    

    一旦您可以在这个级别上工作,数据绑定本身就没有那么有用了。但是,如果您真的想使用它,可以使用 对象列表视图 项目。它让你两全其美。

    对于ObjectListView,没有理由切换到更不有趣的DataGridView。ObjectListView为您提供了使用ListView漂亮的UI功能的DataGridView的便利性,然后还提供了一些其他功能:

    alt text http://i25.tinypic.com/24vo5fb.jpg

        2
  •  2
  •   Bryan Menard    16 年前

    标准的数据绑定可能使您的生活在这里变得更简单。使用A BindingList<T> 可以轻松实现双向绑定。双向绑定使用编程方式(即模型)或用户所做的更改更新UI变得容易。列表将保持同步。

    但是,您可能希望将ListView替换为(只读) DataGridView 如果你负担得起的话。它将使您的like在数据绑定方面变得更加容易。

    dataGridView.DataSource = new BindingList<T>(initialList);
    
        3
  •  1
  •   Philip Wallace    16 年前

    数据绑定是一种方法。看看这篇文章,它非常有帮助:

    Data Binding in .NET / C# Windows Forms

    数据绑定为 开发人员创建读/写链接 在窗体上的控件和 应用程序中的数据(它们的数据 模型)。传统上,数据绑定是 在应用程序中使用 存储在数据库中的数据的优势。 Windows窗体数据绑定允许您 从数据库访问数据 作为其他结构中的数据,例如 数组和集合。

    alt text http://www.akadia.com/img/dotnet_databinding_1.gif

        4
  •  1
  •   jpbochi    16 年前

    我想没有 正确的 解决这个问题的方法。通常,我强烈支持通过各种方式将数据源集合与UI分离。有几种数据绑定解决方案可以将两者结合在一起。

    不管怎样,让我考虑一下你所暴露的观点。

    打开 冗余 :对于用户头脑中基本相同的实体,您确实有两个列表。这些清单根本不对等。

    首先,不会有重复的内存。UI端的列表可能引用了数据源列表中的原始对象,但它只是一个引用。总的内存消耗不会比在UI中有一个集合对象大很多。

    第二,这两个列表(UI和数据源)的项目数可能不同。如果在接口中使用分页,那么UI列表可能比数据源列表小得多。

    论 复杂性 :使用良好的数据绑定解决方案可以大大降低UI与其数据源同步的复杂性。有些情况下,将两个列表分开实际上 简化 您的代码。

    考虑使用单独的窗口/页面/用户控件/负责编辑(新的或旧的)对象的任何对象的可能性。如果您的UI上只有一个对象集合,那么这个单独的组件必须引用保存列表的同一个UI控件。这完全没有道理。

        5
  •  0
  •   ChrisF    16 年前

    访问的问题 ListView (例如)直接地,就是您正在修改内存中数据的“主”副本。这意味着,如果您的用户决定取消他们的更改,您需要能够回滚他们可能做的任何更改。

    所以您可以选择,添加两个数据结构副本的内存,或者在取消时回滚的复杂性。

        6
  •  0
  •   TLiebe    16 年前

    退房 this 关于数据绑定的文章。对于ListView之类的东西,可以绑定到实现列表接口之一的自定义类。通过为事件的自定义类添加支持,您可以在列表发生更改时自动更新GUI(反之亦然)。

        7
  •  0
  •   HardCode    16 年前

    我刚刚用一个列表(myObject)和列表视图来处理这个混乱。ListView的不足之处在于,它不像其他许多对象容器(如ComboBox、ListBox和DataGridView)那样提供.datasource属性。我选择删除ListView而不是DataGridView,仅仅是因为我的要求不需要ListView(我在DataGridView中添加了一个自定义的第一列来呈现图像,这就是我最初选择ListView的原因。但你是对的,让事情保持同步的额外代码太让人头疼了。关于你的问题,做我做的。看看你是不是 真的? 通过考虑是否可以改用DataGridView并满足要求来要求ListView。