如何使用 WPF 中使用网格的模板显示项目集合?
我有一个对象集合,我想将它们表示为 Grid
,每个对象表示为 矩形
(或 Button
- 避风港)尚未确定这一点)。每个对象都有一个 X
和 Y
属性,表示其在 Grid
中的位置。
例如,我可能有四个对象:
var one = new MyClass(){X=0, Y=0}
var two = new MyClass(){X=1, Y=0}
var three = new MyClass(){X=0, Y=1}
var four = new MyClass(){X=1, Y=1}
Grid
应该有两行和两列。对象one
将表示为网格左上角的矩形
。对象two
将位于对象one
右侧的槽中,三
将位于one
下方,并且< code>four 将位于右下角的插槽中。
我试图弄清楚如何以惯用的 WPF 方式创建这两个模板(例如使用 DataTemplate 和类似的构造),但需要一些帮助。有什么建议吗?
我还希望能够将模板存储在主窗口之外的单独文件中,但我也不知道如何做到这一点。
I have a collection of objects that I would like to represent as a Grid
with each object represented as a Rectangle
(or a Button
- haven't settled on this yet). Each object has an X
and a Y
property which represent its location in the Grid
.
For example, I might have four objects:
var one = new MyClass(){X=0, Y=0}
var two = new MyClass(){X=1, Y=0}
var three = new MyClass(){X=0, Y=1}
var four = new MyClass(){X=1, Y=1}
The Grid
should have two rows and two columns. Object one
would be represented as a Rectangle
in the top left part of the Grid. Object two
would be in the slot to the right of object one
, three
would be below one
, and four
would be in the bottom right slot.
I am trying to figure out how to create both templates in an idiomatic WPF manner (e.g. using DataTemplate
and similar constructs), but need some help. Any advice?
I'd also like to be able to store the template(s) in a separate file from my main window, but am not sure how to do that either.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
关于您的第一个问题,这可能是您正在寻找的模式:
在真实的应用程序中,您将
ItemsControl.ItemsSource
设置为Binding
,其源是对象的集合,然后创建一个DataTemplate
,如下所示:至于将代码组织到单独的文件中:您应该考虑创建一个
UserControl
来显示对象,而不是一个数据模板
。创建其中一个并不比创建另一个更困难,并且UserControl
是存在于其自己的 XAML 文件中的类,并且可以像任何其他对象一样通过其名称在 XAML 中实例化。根据您的设计,您可以将网格定位与对象的实际视觉呈现分开,以便您可以在其他地方重用该呈现。这可能就是我的处理方式。为我的对象创建
UserControl
后,我会在Grid.Resources
中创建一个DataTemplate
(因为它描述了特定的Grid 如何
应该显示对象),如下所示:还可以使用类似包含的方法来组织 XAML:创建一个包含资源字典的独立 XAML 文件,然后将字典合并到您的窗口(或应用程序或任何其他内容)中否则真的)资源字典:
这可能是组织大量样式和模板的好方法,但它的问题是,如果设置了
ResourceDictionary.MergedDictionaries
,则无法直接放置任何项目字典中,因此您必须创建一个单独的 XAML 文件来包含仅属于窗口的资源,这有点痛苦。As to your first question, this is probably the pattern you're looking for:
In a real application, you'd set the
ItemsControl.ItemsSource
to aBinding
whose source is a collection of objects, and then create aDataTemplate
like:As far as organizing the code into separate files goes: you should consider creating a
UserControl
for displaying the object, instead of aDataTemplate
. It's no more difficult to create one than the other, andUserControl
s are classes that live in their own XAML files and can be instantiated in XAML, like any other object, by their name.Depending on your design, you might separate out the grid positioning from the actual visual presentation of the object, so that you can reuse the presentation elsewhere. That's probably how I'd approach it. After creating a
UserControl
for my object, I'd create aDataTemplate
inGrid.Resources
(since it's describing how that specificGrid
should display the objects) like this:It's also possible to organize XAML using an include-like approach: create a standalone XAML file that contains a resource dictionary, and then merge the dictionaries into your window's (or application's, or anything else really) resource dictionary:
This can be a good approach for organizing a lot of styles and templates, though a problem with it is that if
ResourceDictionary.MergedDictionaries
is set, you can't put any items directly in the dictionary, so you have to create a separate XAML file to contain the resources that belong solely to the window, which is kind of a pain.一种方法是使用 ListView。您可以将其 ItemsPanel 设置为 Canvas,然后在数据模板中将 Canvas.Top 和 Canvas.Left 绑定到您希望项目具有的 X 和 Y 坐标:
如果需要,您可以使用转换器来相乘YPosition 和 XPosition 按像元大小排列,以便属性可以引用像元数量而不是像素大小。
另一方面(更简单):如果您事先知道网格将有多少行或列,并且每个单元格只有一个元素,那么您可以使用 UniformGrid 而不是 ListView。
One approach would be to use a ListView. You can set it's ItemsPanel to be a Canvas and then in the datatemplate bind the Canvas.Top and Canvas.Left to the X and Y co-ordinates that you want the item to have:
If you need to you can use a converter to multiply the YPosition and XPosition by the cell size so that the properties can refer to the cell number rather than the pixel size.
On the other (simpler) hand: If you know in advance how many rows or columns the grid will have and there is one, and only one, element per cell then you may be able to use a UniformGrid instead of a ListView.