我无法理解 wpf 数据绑定
我的场景: wpf 表单有一个文本框和一个 wpf 工具 数据网格。 当在文本框中输入文本时,我的服务返回一个 IEnumerable
项。 我希望我的数据网格显示此服务的结果。
我尝试用谷歌搜索,但找不到头绪。 我才刚刚开始学习 WPF,大多数使用的术语我都不懂。
我认为我应该将服务的结果放入 ObservableCollection 中,毫不费力。 但后来我想以某种方式将它绑定到我的数据网格。 我怎样才能做到这一点? 网格如何知道要生成哪些列?
My scenario:
A wpf form has a textbox and a wpf toolkig datagrid.
When a text is entered in the textbox, my service returns an IEnumerable<TranslationItem>
items. I want my datagrid to show the result of this service.
I tried googling around, but I can't get heads or tails to it. I'm only starting to learn WPF and most of the used terms elude me.
What I gather is that I should put my service's result in an ObservableCollection, no sweat.
But then I want to somehow bind it to my datagrid. How can I do that? How will the grid know what columns to generate?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
最简单的方法是将 DataGrid 的 ItemsSource 属性设置为 ObservableCollection。
DataGrid 反映该集合中的对象,并为其找到的每个公共属性创建一个列。 有关详细信息,请参阅此处。
如果直接设置 ItemsSource 属性,那么它并不是真正的 wpf 绑定。 当我开始在 WPF 中进行数据绑定时,我发现以下三个链接很有用。
Bea Stollnitz:“{Binding}”是什么意思?
WPF 基本数据绑定常见问题解答< /a>
MSDN:数据绑定操作方法主题
The easiest way is to set the ItemsSource property of the DataGrid to the ObservableCollection.
The DataGrid reflects the objects in that collection and create a column for each public property it finds. See here for more info.
If you set the ItemsSource property directly then it's not really wpf binding. Here's three links I found useful when I started databinding in WPF.
Bea Stollnitz: What does “{Binding}” mean?
WPF Basic Data Binding FAQ
MSDN: Data Binding How-to Topics
虽然 ObservableCollection 可以用于此目的,但根据它的使用方式,您不会从中获得任何好处。 ObservableCollection 的主要功能是它实现了 INotifyCollectionChanged。 该接口的作用是提供通知机制来告诉 UI 属性已更改。 由于 ObservableCollection 已经实现了这一点,如果您将 DataGrid、ListBox、ItemsControl 等的 ItemSource 属性绑定到此类型的集合,则每当添加/删除/替换/移动/重置项目时,它将自动更新 UI。 因此,每次想要使用新的 IEnumerable 结果集更新集合时,都必须首先清除集合,然后添加新结果。
然而,在这种情况下,我会推荐另一种选择而不是 ObservableCollection。 它是使用一个叫做 ObjectDataProvider 的东西。 使用这个我们可以完全避免背后的代码,并且总体上更加干净。 因此,我们在某个地方有我们的服务,在本例中是在我的 Window.xaml.cs 中,
就像您描述的服务一样,它从文本框中获取一个字符串,并返回一个 IEnumerable。 现在,在 XAML 中我们可以使用此服务并调用它。
在窗口声明中,我们添加服务所在位置的命名空间:
现在,在我们的 Window.Resources(或 UserControl,或其他任何地方)中,我们可以引用我们的服务。 一旦我们将服务公开为资源,我们就可以创建一个 ObjectDataProvider 来公开我们希望使用的 Translate 方法。
ObjectDataProvider 是我们的服务的关键,并使用字符串参数调用 Translate 方法。 现在我们要做的就是让它响应我们的文本框。
我们可以通过使用一些 Binding 属性来做到这一点。 我们希望 TextBox 中的 TextProperty 绑定到 ObjectDataProvider,因此我们将 Source 属性设置为指向它。 在 Path 中,我们想要绑定到的 ObjectDataProvider 部分是 MethodParameter。 现在,我们将其设置为直接绑定到该属性的源,并且仅以一种方式传输,这意味着 ObjectDataProvider 的方法参数不会更新 TextBox 的文本。 最后,我们可以将 UpdateSourceTrigger 设置为 PropertyChanged,告诉绑定在对象数据提供程序中设置我们要绑定到的源,只要文本发生任何更改。
剩下的就是在 Grid 中设置 ItemsSource,或者在本例中设置一个简单的 ListBox。
关于 DataGrid 的最后一部分:
如果您使用的是 WPFToolkit 的数据网格,它确实具有可以通过属性设置的自动生成功能,并且您可以找到有关它的更多信息 此处。
While an ObservableCollection can be used for this, depending on how it is used you won't recive any benifit from it. The key feature of the ObservableCollection is that it implements INotifyCollectionChanged. What this interface does is provide a notifcation mechanism to tell the UI that a property has changed. Since ObservableCollection already implements this, if you bind your DataGrid, ListBox, ItemsControl, etc.'s ItemSource property to a collection of this type it will automaticly update the UI any time an item is Added/Removed/Replaced/Moved/Reset. Because of this, every time you want to update the collection with a new IEnumerable result set, you will have to first clear the collection, and then add the new results.
However, there is another option that I would recommend over an ObservableCollection in this case. It is to use something called an ObjectDataProvider. Using this we can avoid the code behind entirely, and it is overall much cleaner. So we have our service somewhere, in this case in my Window.xaml.cs
Like the service you describe, it takes it a string from a textbox, and returns an IEnumerable. Now, in the XAML we can use this service and make calls to it.
In the window declerations, we add the namespace for where the service is located:
Now, in our Window.Resources (Or UserControl, or anywhere else) we can reference our service. Once we have exposed our service as a resource, we can create an ObjectDataProvider that exposes the Translate method we wish to use.
The ObjectDataProvider is keyed to our Service and calls the Translate method with a String parameter. Now all we have to do is get it to respond to our text box.
We can do this by making use of some of the Binding properties. We want our TextProperty in the TextBox to bind to the ObjectDataProvider, so we set the Source property to point to it. The part of the ObjectDataProvider that we want to bind to, in the Path, is the MethodParameter. Now, we set it to Bind directly to the source of that property, and to only travel one way, meaning that the ObjectDataProvider's method parameter won't update the TextBox's text. Finally we can set the UpdateSourceTrigger to PropertyChanged, telling the binding to set the source we are binding to, in the object data provider, whenever there is any change to the text.
All that's left is to set the ItemsSource in the Grid, or a simple ListBox in this case.
Regarding the final part on the DataGrid:
If you are using the WPFToolkit's data grid, it does have an auto generate feature that can be set through the properties, and you can find more info on it here.
您将网格的 DataSource(甚至 DataContext)设置为 Observable Collection。
我不熟悉该数据网格,但大多数网格都可以选择将可观察集合中类型的所有公共属性公开为列,或者在 XAML 中显式设置列布局,并且列定义的属性之一是用于列数据的对象的属性。
例如,对于 Infragistics 数据网格
名称,您可以在其中设置要使用的对象的属性。
You set the DataSource (or even the DataContext) of the grid to your Observable Collection.
I'm not familiar with that data grid, but most grids have options to either expose all public properties of the type in the Observable Collection as columns, or you explicitly set a column layout in XAML and one of the properties of the column definition is the property of the the object to use for the column data.
e.g. with Infragistics Data Grid
Name is where you set the property on the object to use.
您的网格可以直接构建列,也可以指定您想要的列类型。 如果您观看此 视频,它会解释它。 这是针对 VS2010 的,但 VS2008 的基本原理是相同的——尽管实现略有不同,因为它不太集成。
至于如何绑定,请将保存项目的 ObservableCollection 分配给网格的 ItemsSource 属性。
your grid can either build the columns directly, or you can specify the column types that you wish. If you watch this video, it'll explain it. That's for VS2010, but the fundamentals are the same for VS2008--though implementation is just slightly different, as it's not quite as integrated.
As for how to bind, assign the ObservableCollection that holds your items to the ItemsSource property of the grid.