Silverlight 中列表同步的建议
我们正在公司创建一个业务应用程序 (Silverlight 4),在我们的几个视图中,我们使用该功能来同步某种类型的两个列表。
更精确的是,目前我们使用两个列表框(一个源和一个目标)和两个按钮(一个添加和一个删除)。源列表和目标列表都绑定到具有相同数据类型的集合。
用户可以选择源列表中的一个或多个项目并按下添加按钮以将项目移至目标列表(即,将项目从源中移除并添加至目标)。
同样,用户可以选择目标列表中的一项或多项,然后按删除键将项目从目标移回源列表。
还可以添加一条验证规则,规定用户必须向目标列表中添加至少一项。
非常简单...
到目前为止,我们使用自己创建的用户控件,该控件封装了这 4 个控件(2 个列表框和 2 个按钮)以及保持列表同步的逻辑。依赖属性用于绑定源集合和目标集合。
现在来说说问题。我们的客户现在希望我们的用户控制更加灵活。 他们希望能够在源列表和目标列表中具有任意数量的列(即源列表可能具有与目标列表不同的列和不同数量的列)。客户还希望能够对任何列进行排序。
我的第一个想法是将列表框替换为数据网格。但后来我意识到我不知道如何以一种简单的方式让消费者(开发人员)定义他或她的列和绑定。这可能是我对 SL 的了解有限。也许自定义用户控件不是正确的选择?
我将不胜感激任何形式的帮助。现在我们在我们的观点中一遍又一遍地实施相同的逻辑,但感觉不对。我们必须有某种方法可以使其成为易于使用的可重用组件。
谢谢!
We are creating a business application (Silverlight 4) at our company where we, in several of our views, use the functionality to synchronize two lists of some kind.
More precise we are, at the moment, using two list boxes (one source and one target) and two buttons (one add and one remove). Both the source list and the target lists are bound to collections with the same data type.
A user may select one or more items in the source list and press the add button to have the items moved to the target list (i.e. the items are removed from the source and added to the target).
Likewise the user could select one or more items in the target list and press remove to have the items moved from the target back to the source list.
There is also the possibility to add a validation rule that says that the user must add at least one item to the target list.
Pretty simple...
Until now we are using our own created user control which incapsulates these 4 controls (2 list boxes and 2 buttons) and the logic for keeping the lists in sync. Dependency properties are used for binding the source and target collections.
Now to the problem. Our customer now wants our user control to be more flexible.
They want to be able to have an arbitray number of columns in both the source and target list (i.e. the source list may have different columns and a different number of columns than the target list). The customer also wants to be able to sort on any column.
My first thought was to replace the list box to the data grid instead. But then I realized I don't know how to, in an easy way, let the consumer (the developer) define his or her columns and bindings. This may be to my limited knowledge of SL. Maybe a custom user control isn't the way to go?
I would appreciate any kind of help. Right now we are implementing the same logic over and over again in our views and it doesn't feel right. There has to be some way we can make this a reusable component that is easy to use.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于您要创建一个供其他开发人员使用的控件,因此通常最好使用模板控件而不是
UserControl
。在这种情况下,开发人员可以为控件指定自定义模板。然而,这并没有你想象的那么有帮助,特别是如果两个网格的标题集相同的话。您可以采取的一种方法是提供名为“ListTemplate”的
DataTemplate
类型的依赖属性。在控件 Xaml 中显示列表的两个点上,使用两个ControlPresenter
元素。一个名为“SourceContent”,另一个名为“TargetContent”。对于两者都将ContentTemplate
绑定到这个新的“ListTemplate”。对这些演示器上的
Content
属性的分配进行编码,然后为演示器已加载的ItemsControl
或DataGrid
的 ItemsSource 分配适当的集合。如果您包含一个简单的
ListBox
基本数据模板作为“ListTemplate”属性的默认值,那么您的控件应该以其最简单的形式可用,但如果开发人员想要使用DataGrid
对于各种列,他们可以在ListTemplate
属性。当然,您需要在控件中编写代码来处理可能是
DataGrid
元素的列表。Since you are creating a control to be consumed by other developers then its usually best to be using a Template Control rather than a
UserControl
. In which case the developers can specify a custom template for the control. However that's not as helpful as you could be, especially if the set of headers for both grids are the same.One approach you could take is to provide dependency property of the type
DataTemplate
called "ListTemplate". At the two points in your controls Xaml where you would display the lists use twoControlPresenter
elements. One named "SourceContent" the other "TargetContent". For both bindContentTemplate
to this new "ListTemplate".Code up the assignment of the
Content
property on these presenters and then assign the appropriate collection the ItemsSource of either theItemsControl
orDataGrid
the presenter has loaded.If you include a simple
ListBox
base data template as the default value for the "ListTemplate" property then you control should be usuable in its simplest form yet if the developer wants use aDataGrid
with various columns they can define one in theListTemplate
property.Of course you will need to write code in your control to cope with the lists possibly being a
DataGrid
elements.答案的“列表版本”
(另请参阅网格版本)
自定义控件听起来很适合此目的,但您希望两个列表都被模板化,以便开发人员可以定义每个项目的视图。我假设您不需要标题,所以一直使用列表框。下面的测试代码会产生这样的结果:
由于列表框已经有项目模板,您确实希望将它们公开为属性在您的自定义用户控件中。然后,您可以单独编辑 2 个模板(下面的示例只是将 Left 和 Right 模板设置为相同的 FirstName/LastName 堆栈面板,您可以在此处定义以下格式您的列表框):
示例 ListSelectionControl XAML 如下:
以及控件的简单隐藏代码:
为了完成示例,这是填充示例 GUI 的隐藏代码:
"List version" of the answer
(see also the grid version)
A custom control sounds right for this, but you want both lists to be templated so the developer can define the per item views. I have assumed you do not need headings so have stuck with listboxes. The test code below results in this:
As the listboxes already have item templates, you really want to expose those as properties in your custom user control. You can then edit the 2 templates individually (the example below simply has both Left and Right templates set to the same FirstName/LastName stackpanel, this is where you define the format of your listboxes):
The example ListSelectionControl XAML is below:
And the simple code-behind of the control:
And just to complete the example, this is the code behind to populate the sample GUI:
答案的“网格版本”:(
参见下面的列表版本)
由于问题已更改(已澄清),我正在添加一个新答案。第一个对于那些只想要列表的人来说仍然有用,所以我将其留在那里。
要对网格执行类似的操作,您不需要公开模板,因为数据网格列不是模板化的(它们是控件列表,可以单独模板化)。
相反,您将左网格和右网格列集合公开为属性,并只需设置控件的 LeftColumns 和 RightColumns 属性在您的父页面中。唯一的技巧是数据网格列集合没有设置器,因此您需要从新的属性集合更新网格集合项:
隐藏代码现在是:
控件的 Xaml 现在是:
测试页的 Xaml(定义列)现在是:
后面的测试代码现在是:
"Grid version" of the answer:
(see list version below)
As the question has changed (clarified) I am adding a new answer. The first one is still useful for those that only want lists so I will leave it there.
To do a similar thing with grids you don't expose the templates as datagrid columns are not templated (they are lists of controls, which can individually be templated).
Instead you expose the left grid and right grid column collections as properties and simply set the LeftColumns and RightColumns properties of the control in your parent page. The only trick is that the datagrid-column collections have no setter so you need to update the grid collections items from the new property collections:
The code-behind is now:
The Xaml of the control is now:
The Xaml of the test page (which defines the columns) is now:
And the test code-behind is now: