WPF:如何动态创建具有连续数字的 x 行和 y 列的网格
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34009584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF: How to dynamically create a grid with x rows and y columns with consecutive numbers
提问by wpfNewbie
I am completely new to wpf and c#, so excuse if this is super trivial question. I am trying to create a fairly simple control.
我对 wpf 和 c# 完全陌生,所以请原谅这是一个非常微不足道的问题。我正在尝试创建一个相当简单的控件。
This grid will always have consecutive numbers, with a color rectangle in front of it. Clicking on the gray rectangle will change its color, and set the text to bold (I will deal with these triggers later).
这个网格总是有连续的数字,在它前面有一个彩色矩形。单击灰色矩形将更改其颜色,并将文本设置为粗体(稍后我将处理这些触发器)。
For now, I just need to figure out how to create this control dynamically. When the program starts, it needs to one time create this control, and then the size won't change. I need to tell it the number of columns and rows (each column will probably always have 8 elements), and have it populate with consecutive numbers with specific font style/rectangle color.
现在,我只需要弄清楚如何动态创建此控件。当程序启动时,它需要一次创建这个控件,然后大小不会改变。我需要告诉它列数和行数(每列可能总是有 8 个元素),并让它填充具有特定字体样式/矩形颜色的连续数字。
I was experimented with creating a stackpanel UserControl for rectangle/label combo, passing the style to it, and then adding 32 of these UserControls in specific row/column in a grid. But I would need the size of that grid to be dynamic, so I need some for loop in the code I think.
我尝试为矩形/标签组合创建一个堆栈面板 UserControl,将样式传递给它,然后在网格的特定行/列中添加 32 个这些 UserControl。但是我需要该网格的大小是动态的,所以我认为代码中需要一些 for 循环。
Thanks!
谢谢!
回答by Rachel
I would start with an ItemsControl
我会从一个 ItemsControl
You can give it a collection of items, and it will render each item however you want, displayed in any panel you want.
你可以给它一个项目集合,它会按照你想要的方式呈现每个项目,显示在你想要的任何面板中。
For example, you might have something like this
例如,你可能有这样的事情
<ItemsControl ItemsSource="{Binding MyCollection}">
<!-- This panel will be used to hold the items -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="8" Columns="8" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Each item will be drawn using this template -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Text="{Binding }" Style="{StaticResource MyButtonStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The Rowsand Columnsproperty of the UniformGrid are DependencyProperties, so you could bind them to properties on the DataContext to make them dynamic.
UniformGrid的Rows和Columns属性是 DependencyProperties,因此您可以将它们绑定到 DataContext 上的属性以使其动态化。
The only problem with a UniformGridis it only arranges items Horizontally. If you want to display them Vertically, you can either create a custom UniformGrid, or switch to a different panel such as a WrapPanel. If you are new to WPF Panels, I would recommend reading through WPF Layouts - A Quick Visual Start.
a 的唯一问题UniformGrid是它只能水平排列项目。如果要垂直显示它们,可以创建自定义 UniformGrid,或切换到其他面板,例如WrapPanel. 如果您不熟悉 WPF Panels,我建议您通读WPF Layouts - A Quick Visual Start。
The ItemTemplate can be anything. Personally I would use a Button so you have the Click or Command behavior to handle that event, and just overwrite the Button's Template to look however you want. It is an easy task to include your Triggers in there too.
ItemTemplate 可以是任何东西。就我个人而言,我会使用 Button 以便您拥有 Click 或 Command 行为来处理该事件,只需覆盖 Button 的模板即可查看您想要的外观。将触发器包含在其中也是一项简单的任务。
And if you wanted selection behavior, I would recommend switching from an ItemsControl to a ListBox, and overwriting that Template the same way, however it doesn't sound like you need it though, so I think an ItemsControl is better :)
如果您想要选择行为,我建议您从 ItemsControl 切换到 ListBox,并以相同的方式覆盖该模板,但是听起来您并不需要它,所以我认为 ItemsControl 更好:)
回答by Michaela
I would try using a listview and change the template to the style you want to use for your elements.
我会尝试使用列表视图并将模板更改为要用于元素的样式。
To limit the number of items in a row you can use
要限制您可以使用的行中的项目数
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
That way you would always get 3 elements in a row, like
这样你总是会连续得到 3 个元素,比如
123
123
456
456
To make the 3 dynamic you can databind it to some value in your codebehind / viewmodel
要使 3 动态,您可以将其数据绑定到代码隐藏/视图模型中的某个值
to dynamically create the elements within the listview you can add objects to a list/observable collection and then add those to the listview via
要在列表视图中动态创建元素,您可以将对象添加到列表/可观察集合,然后通过以下方式将它们添加到列表视图
listviewname.ItemSource=ListName;
Or however you like. They will get arranged according to how many columns you tell the grid to have. Adding 32 items (with uniform grid of 4) leads to
或者随心所欲。它们将根据您告诉网格具有的列数进行排列。添加 32 个项目(具有 4 个统一网格)导致
1 2 3 4
1 2 3 4
5 6 7 8
5 6 7 8
9 10 11 12
9 10 11 12
...
...
回答by Jorgel
On your page you must create a "main" element, for example a Grid. Give it a name, so that we can access it by code. Here I gave it the name of root
在您的页面上,您必须创建一个“主要”元素,例如网格。给它一个名字,这样我们就可以通过代码访问它。在这里我给它起了个名字root
So you will have something like
所以你会有类似的东西
<Page
... >
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
x:Name="root">
</Grid>
</Page>
Then, on the .cs file of this page you must create a function with the code below. You can call this function on the MainPage() function.
然后,在此页面的 .cs 文件中,您必须使用以下代码创建一个函数。您可以在 MainPage() 函数上调用此函数。
This loop will create one Grid column with dynamic Grid rows
此循环将创建一个带有动态网格行的网格列
// Create a Grid and add it to a component of your page
Grid mainGrid = new Grid();
root.Children.Add(mainGrid);
for (int i = 0; i < 8; i++)
{
// I am creating a Grid with a TextBlock inside,
// it will have the same apperance as a Rectangle,
// but this way you can have a Text inside
Grid g = new Grid();
TextBlock tb = new TextBlock();
tb.Text = i.ToString();
g.Children.Add(tb);
// Here you set the Grid properties, such as border and alignment
// You can add other properties and events you need
g.BorderThickness = new Thickness(1);
g.BorderBrush = new SolidColorBrush(Colors.Black);
g.HorizontalAlignment = HorizontalAlignment.Stretch;
g.VerticalAlignment = VerticalAlignment.Stretch;
// Add the newly created Grid to the outer Grid
mainGrid.RowDefinitions.Add(new RowDefinition());
mainGrid.Children.Add(g);
// Set the row of the Grid.
Grid.SetRow(g, i);
}
I used a Grid instead of a Rectangle since Rectangles can't have Children.
我使用了 Grid 而不是 Rectangle,因为 Rectangles 不能有 Children。
It must be easy to create the other columns as well, using the same logic that I used to create the Rows.
使用与创建行相同的逻辑,也必须很容易创建其他列。


